【问题标题】:What is the correct layer to configure your IoC container when using a service layer?使用服务层时配置 IoC 容器的正确层是什么?
【发布时间】:2010-01-19 20:53:19
【问题描述】:
我有一个中型的 asp.net MVC 应用程序。它使用一个服务层来处理所有存储库的使用、调用域服务等。我的控制器操作非常苗条——它们基本上调用一个服务类,获得响应并显示该响应。大多数组件都是基于接口的,带有一些穷人的 DI。该应用正在成长,需要更好的测试支持,并开始需要 IoC 容器。
我阅读的所有内容(例如this SO question)都表明我应该在应用程序根目录配置 IoC。如果我直接从控制器操作中使用存储库并且在控制器级别需要 DI,这对我来说是有意义的,但我不是。似乎我希望我的组合根植于我的服务层。我一直在想,我不希望 UI 层的 web.config(或其他配置)甚至提及/看到/听到有关存储库、信用卡处理器等的信息。
我是否以正确的方式思考这个问题,还是我只需要克服它?
【问题讨论】:
标签:
dependency-injection
ioc-container
【解决方案1】:
我和你有同样的情况,我如下解决。
我使用的一般规则是任何有 global.asax 或类似的东西,它需要执行注册 IoC 组件的代码。另一种说法是,您需要为每个正在运行的不同进程运行它(即网站在一个进程中,而服务在另一个进程中)。
在我的情况下,我为 mvc 网站 global.asax 执行一次,然后为服务器执行一次。在这种情况下,服务和网站之间的注册会有所不同。
此外,我还做一件事。由于我在 mvc 应用程序和服务之间重用组件(即日志记录),我有第三个核心组件,它为系统注册核心 IoC 组件,并且该组件由网站和服务注册调用。因此,服务和网站之间的任何共同点都进入核心注册,然后任何不同的都进入“接口”特定注册。
希望对您有所帮助。
【解决方案2】:
你只需要克服它:)
在应用程序根目录中拥有 Composition Root 并不要求您在 web.config 中拥有大量 DI Container 内容。如果你愿意,你可以,但它是可选的。 不是可选的 将 Composition Root 放入应用程序根目录时,您需要在 Global.asax 中有一些 DI 代码。
你可能会觉得这无关紧要,因为你的控制器太薄了,但这不是重点。实际上,您(抽象的“您”)希望将耦合类推迟到最后负责的时刻。越早组合类型,灵活性就越低。
如果您在服务层中耦合类,您将在此时做出不可逆转的决定。如果后来发现您需要以不同的方式组合这些服务,那么您就不能 - 除非重新编译,否则。
如果这样做有很大的好处,我可以理解您为什么想要这样做,但没有。您也可以等待编写所有组件,直到您绝对必须这样做 - 这就是应用程序的入口点。
【解决方案3】:
从 Java 的角度来看,我将 Spring 框架用于我的 IoC 容器。有了它,容器真的是应用程序范围的。尽管您可以为不同的层设置不同的配置文件(持久性配置文件、服务配置文件、控制器配置文件等),但所有对象(Java 术语中的 bean)都进入容器。
我认为这仍然可以,因为您提到的类之间没有耦合。视图不需要知道信用卡处理器,因为它们在同一个 IoC 容器中。这些类将只接收(通过注入)它们需要的依赖项,而不关心容器中的其他对象。