Phi*_*thy 2 asp.net-mvc dependency-injection unity-container asp.net-mvc-5
我正在使用存储库和服务层设计模式构建 ASP.NET MVC 5 应用程序。我已经使用 unity 将我的服务注入到我的控制器中。
这工作得很好,直到现在我还不需要考虑实例化任何需要在控制器外部注入接口的对象。但是,在配置应用程序启动以在数据库中设置一些用户时,我需要这样做。
为此,我想使用我UsersService构建的。我想到,随着应用程序的增长,肯定会在其他情况下我想做同样的事情,例如从另一个服务中调用一个服务。
我发现我可以实例化一个 Unity 容器并调用它的解析来获取我的新服务实例:
IProductService productService = container.Resolve<IProductService>();
Run Code Online (Sandbox Code Playgroud)
然而,这对我来说有点难闻,让容器泄漏到我的应用程序中似乎是一种反模式。那么有没有更好的方法来做到这一点呢?
Unity 和其他依赖注入容器会自动执行此操作。当您将服务注入控制器时,它将自动解析该服务的整个依赖关系图。您不仅可以解决服务及其依赖项的依赖关系,还应该将依赖项注入到需要它们的服务而不是控制器中。
任何具有多个依赖项的类(包括控制器)都会有一种代码味道,表明您违反了单一职责原则,并且您很可能应该重构以聚合服务。
是的,将容器注入到组合根之外的任何点是一种称为服务定位器的反模式。
对于在控制器外部注入服务,区分可注入数据和运行时数据非常重要。例如,有些尝试将服务注入 DTO 对象、属性、静态类/扩展方法以及其他与注入服务相反的地方。对于这些情况,正确评估情况并重构为 DI 友好的解决方案非常重要 - 优先使用构造函数注入而不是其他替代方案,并考虑将服务定位器作为最后的手段。例如,如果您尝试使用依赖服务创建扩展方法,很可能您有一些功能本身应该是非静态服务,DTO 永远不应该从 DI 容器创建,并且您可能必须使用MVC 中的多个扩展点,您可以在应用程序的组合根中注入容器,这不构成服务定位器。
这值得么?通常。得到了什么?与紧密耦合的应用程序相比,您能够以应用程序设计者甚至没有预料到的方式更快地更改应用程序。因此,确保应用程序松散耦合的额外成本通常可以在项目的持续维护中得到补偿。附带的好处是,您能够轻松地独立于其他组件对每个组件进行单元测试。