是否应该为依赖注入许多"级别"而不是需要它?

bin*_*nks 5 c# dependency-injection

我正在使用SOLID原则编写C#ASP.NET MVC Web应用程序.

我写了一个ViewModelService,这取决于a AccountService和a RepositoryService,所以我已经注入了这两个服务ViewModelServer.

PermissionService依赖于HttpContextBase以使用GetOwinContext()获得的一个实例UserManager.控制器有一个HttpContextBase需要使用的实例- 所以我似乎必须将HttpContextBase实例注入到ViewModelService然后将其注入到实例中PermissionService.

所以,就代码而言,我有:

public ViewModelService

public CategoryRepository(ApplicationDbContext context, IPermissionService permissionservice)

public AccountService(HttpContextBase httpcontext, IPrincipal securityprincipal)
Run Code Online (Sandbox Code Playgroud)

为了实例化ViewModelService,我接着这样做:

new ViewModelService(
    new CategoryRepository(
            new ApplicationDbContext(), 
            new PermissionService(
                new AccountService(HttpContext, Thread.CurrentPrincipal),
                new UserPasswordRepository(new ApplicationDbContext()),
                new ApplicationSettingsService())),
    new PasswordRepository(
            new ApplicationDbContext(), 
            new PermissionService(
                new AccountService(HttpContext, Thread.CurrentPrincipal), 
                new UserPasswordRepository(new ApplicationDbContext()),
                new ApplicationSettingsService())),
    new ModelValidatorService());
Run Code Online (Sandbox Code Playgroud)

应该从多个"级别"注入依赖关系,还是有更好的方法?

Dav*_*vid 5

有一个平衡点需要达成。

一方面,您的思想流派坚持认为所有依赖项都必须由类公开才能“正确”注入。(这个学派认为服务定位器之类的东西是一种反模式。)这样做有其优点,但走向极端,你会发现自己处于现在的位置。某些复合模型本身具有复合模型,其复杂性恰到好处,会导致聚合根需要注入大量依赖项来满足更深层次模型的依赖项。

我个人发现这会在这种情况下产生耦合。这就是 DI 旨在解决的问题,而不是创造的问题。

另一方面,您有允许服务定位器方法的思想流派,其中模型可以在内部调用一些公共域服务来解决它的依赖关系。这样做有其优点,但极端情况下,您会发现您的依赖项不太为人所知,并且如果无法解决任何给定的依赖项,则可能会出现运行时错误。(基本上,您可能会在更高级别上收到错误,因为消费对象永远不知道消费对象需要未提供的东西。)

就我个人而言,我经常使用服务定位器方法(主要是因为它是一种非常方便的模式,用于将 DI 引入遗留域,作为更大的重构练习的一部分,这是我专业做的很多事情)并且从未遇到过这样的情况问题。

阴阳皆有之。我认为每个解决方案空间都有自己的平衡。如果您发现直接喷射使系统难以维护,则可能值得调查维修地点。相反,如果整个领域模型本身本质上是耦合的,并且这个 DI 问题只是该耦合的症状而不是其原因,那么也可能值得研究。

  • 我站在服务定位器这一边,它是一种反模式和构造函数注入,单一组合根是唯一的正确方式,但这显然有点像一场圣战。关于 Mark Seemann 的原始博客文章有一个不错的讨论,声明服务定位器是一个反模式,值得一读:http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ (3认同)
  • @PrestonGuillot:西曼在这个主题上提出了“很多”好的观点,而且当然比我表达得更好。(我还向任何认真对待 DI 的人强烈推荐他的书,因为这不仅仅是在混合中添加另一个框架。)它经常确实成为一场圣战,在实际的商业软件中,这场战争不是由教条式的声明决定的,而是由底线。*如果*可以将域重构为更简单的模型图,从而使问题变得毫无意义,那么我将支持不使用服务定位器。但实际上,这是一个很大的“如果”。 (2认同)