使用Unity在控制器外部进行ASP.NET MVC依赖注入

时间:2017-02-18 06:20:58

标签: asp.net-mvc dependency-injection asp.net-mvc-5 unity-container

我正在使用存储库和服务层设计模式构建ASP.NET MVC 5应用程序。我已经使用unity将我的服务注入我的控制器。

这很好用,直到现在我还没有必要考虑实例化需要在控制器外部注入接口的任何对象。但是,在配置应用程序启动以设置数据库中的某些用户时,我需要这样做。

为此,我想要使用我已构建的UsersService。我发现随着应用程序的增长,我肯定会遇到其他需要做同样事情的情况,例如从另一个服务中调用服务。

我看到我可以实例化Unity容器并在其上调用resolve来获取我的新服务实例:

IProductService productService = container.Resolve<IProductService>();

然而,这种气味对我来说,让我的应用程序泄漏的容器似乎是一种反模式。那么有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

Unity和其他依赖注入容器会自动执行此操作。将服务注入控制器时,它将自动解析该服务的整个依赖关系图。您不仅可以解决服务及其依赖关系的依赖关系,将依赖关系注入需要它们的服务而不是控制器。

任何具有多个依赖关系的类(包括控制器)都是违反Single Responsibility Principle的代码气味,您最有可能refactor to aggregate services

是的,将容器注入composition root以外的任何位置都是an anti-pattern called a service locator

对于控制器之外的注入服务,区分injectables and runtime data很重要。例如,有些人试图将服务注入DTO对象,attributes,静态类/扩展方法,以及其他注入服务的反模式的地方。对于这些情况,正确评估情况并重构DI友好解决方案非常重要 - 有利于构造函数注入而不是其他替代方案,并将服务定位器视为最后的手段。例如,如果您尝试使用依赖服务创建扩展方法,则很可能您有一些本身应该是非静态服务的功能,DTO不应该从DI容器创建,并且您可能必须在MVC中使用多个扩展点,其中将容器注入应用程序的组合根目录中,而不构成服务定位器。

值得吗?通常。得到了什么?与使用应用程序设计人员甚至无法预料的紧密耦合应用程序相比,您可以更快地更改应用程序。因此,确保应用程序松散耦合的额外成本通常不仅仅是在项目的持续维护中得到补偿。作为附带好处,您可以轻松地对每个组件进行单元测试,而不受其他组件的影响。