我已经读过马克·西曼(Mark Seemann)的一本书"Dependency injection in .NET",它让我看到很多东西。但仍然很少有问题。这是其中之一:
假设我们有一个WCF服务公开API,用于处理某些数据库:
public class MyService : IMyService
{
private ITableARepository _reposA;
private ITableARepository _reposB;
//....
public IEnumerable<EntityA> GetAEntities()
{
return _reposA.GetAll().Select(x=>x.ToDTO())
}
public IEnumerable<EntityB> GetBEntities()
{
return _reposB.GetAll().Select(x=>x.ToDTO())
}
//...
}
可能有数十个存储库服务依赖。有些方法使用一种方法,有些方法使用另一种方法,有些方法使用的是少量存储库。
我的问题是如何正确组织存储库依赖项注入服务?
我看到的选项:
或者这个关系存在一个概念上的问题1到多个依赖关系?
我认为答案应该根据服务实例上下文模式而有所不同(可能是它的单个实例,构造函数注入很好;对于PerCall选项3看起来最好忽略上面的警告;对于perSession,一切都取决于会话生命周期:它是否更接近单实例或PerCall。
如果它确实依赖于实例上下文模式,那么就很难对其进行更改,因为更改需要对代码进行大的更改(从构造函数注入转移到属性注入或存储库工厂)。但是WCF服务的整个概念确保了更改实例上下文模式很简单(并且我不太可能需要更改它)。这让我对DI和WCF组合更加困惑。
有人能解释一下如何正确解决这个案子吗?
答案 0 :(得分:5)
使用几十个参数创建一个巨大的构造函数
您不应该创建具有大量构造函数参数的类。这是constructor over-injection代码气味。拥有大量参数的构造函数表明这样的类太多了:违反了Single Responsibility Principle。这导致代码难以维护和扩展。
你测量过这个吗?构造函数参数的数量应该主要是对应用程序的性能不敬。这不应该导致任何明显的性能差异。如果确实如此,那么现在应该看看构造函数所做的工作量(自injection constructors should be simple)或时间切换到更快的DI容器(如果构造函数很简单)。创建一堆服务类通常应该非常快。同样,它对性能非常不利,因为每个未使用的存储库都是浪费资源
即使它没有使用单独的数据库连接。
构造函数不应该首先打开连接。再说一次:它们应该是simple。
物业注入。优化性能 该服务的创建者应该如何知道为特定方法调用初始化哪些属性
调用者无法可靠地确定需要哪些依赖项,因为通常只需要构造函数参数。需要属性会导致temporal coupling,并且您将失去编译时支持。
由于调用者无法确定需要哪些属性,因此需要注入所有属性,这使得性能与构造函数注入等效,我说 - 根本不应该成为问题。
有些非标准(未在书中描述)方法:创建存储库工厂并依赖它而不是具体的存储库。
您可以注入存储库提供程序,而不是注入存储库工厂,这种模式更为人所知的是Unit of Work pattern。工作单元可以访问存储库。
我认为答案应根据服务实例上下文模式而有所不同
不,因为你永远不应该使用WCF&#39; Single&#39;模式。在大多数情况下,您注入WCF服务的依赖项不是线程安全的,不应该超过单个请求。将它们注入单个WCF服务会导致Captive Dependencies,这很糟糕,因为它会导致各种并发错误。
这里的核心问题似乎是您的WCF服务类很大并且违反了单一责任原则,导致它们难以创建,维护和测试。通过以下方式修复此违规行为: