如何避免“;标题“;接口并使用autofac
本文关键字:autofac 标题 何避免 接口 | 更新日期: 2023-09-27 17:59:16
我读了很多关于设计最佳实践的文章。最近,我看到了马克·西曼的这篇文章。在这篇文章中,他陈述了
"您是否从类中提取接口以实现松耦合?如果是这样,那么您的接口之间可能存在1:1的关系以及实现它们的具体类。这可能不是这是一个好兆头,违反了重用抽象原则(RAP)。我已经对此感到内疚,不喜欢结果。"
现在,我已经为DI使用Autofac很多很多年了。我注意到,为了真正实现一个具体的类作为接口,我基本上必须违反这个"原则",为每个类创建接口,我需要在测试中交换实现,或者注入到其他服务中。
例如:
builder.RegisterType<AcknowledgementRepository>()
.As<IAcknowledgementRepository>();
builder.RegisterType<ChangeLogRepository>()
.As<IChangeLogRepository>();
builder.RegisterType<HistoryCycleRepository>()
.As<IHistoryCycleRepository>();
这是一种非常常见的模式,我经常看到它被使用。但是,这似乎是一个坏设计的迹象。
我对其他人如何避免创建这些"头"接口很感兴趣,似乎解决方案可能与使用.AsImplementedInterface()有关,但我还没有充分利用它。
编辑:我应该注意,上面的存储库继承了IGenericRepository,但在许多情况下也扩展了它。
我可以通过以下步骤简单地重构我的代码库来解决这个问题:
我的所有存储库都实现了IRepostory并继承了BaseRepository类,其中很少有存储库真正覆盖了基本存储库中的任何功能。因此,我没有创建一堆I___Repository,而是简单地以这种方式使用autofac。
builder.RegisterType<MemberRepository>().As<IRepository<Member>>();
然后我只需要把我的注射改成这样:
private readonly IRepository<Member> _memberRepo;
//constructor
public MyService(IRepostiory<Member> memberRepo)
{
_memberRepo = memberRepo;
}
我在一些repo中仍然有一些额外的功能,并意识到这些方法实际上表明一个存储库更像是数据字典的历史记录。因此,我制作了另一个名为ICustomDictionaryLookup
的接口
然后,当我在autofac中注册我的服务时,我注册了每个接口的具体实现。
builder.RegisterType<DictionaryRepostiory>().As<IRepository<CustomDictionary>>();
builder.RegisterType<DictionaryRepostiory>().As<ICustomDicionary>();
这很好,因为它分离了抽象,并允许我灵活地选择哪些具体实现将实现特定的功能。现在,我没有理由不能注册DictionaryRepository作为CRUD和另一个完全不同的ICustomDictionary。
只依赖于检索自定义字典而不对字典表执行CRUD操作的方法甚至不需要知道基类中存在CRUD功能,因为它是不相关的。
我很高兴我走上了这条路,因为我的代码好多了。