【问题标题】:ASP.NET MVC dependency injection outside the controller with Unity使用 Unity 在控制器外部进行 ASP.NET MVC 依赖注入
【发布时间】:2017-02-18 06:20:58
【问题描述】:

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

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

为此,我想使用我构建的UsersService。我突然想到,随着应用程序的增长,肯定会有其他场合我想做同样的事情,例如从另一个服务中调用一个服务。

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

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

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

【问题讨论】:

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


    【解决方案1】:

    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 中使用多个扩展点,在其中将容器注入到应用程序的组合根中,这并不构成服务定位器。

    值得吗?通常。得到了什么?与拥有紧密耦合的应用程序相比,您能够以应用程序设计者甚至没有预料到的方式更快地更改应用程序。因此,确保应用程序松散耦合的额外成本通常在项目的持续维护中得到补偿。作为附带的好处,您可以轻松地对每个组件进行独立于其他组件的单元测试。

    【讨论】:

    • 好的,感谢您确认存在服务定位器问题。我可以看到,如果注入的服务超过 3 个,则需要进行重构。至于您提到的整个依赖关系图,我认为这意味着统一计算出需要注入哪些依赖项,以及还需要注入这些依赖项的哪些依赖项等等。既然如此,那么如果我在控制器之外,我该如何避免这样的事情: IService1 service1 = new Service1(new Service2(new Service3())) 其中 service1 依赖于 service2 依赖于 service3;
    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    相关资源
    最近更新 更多