【问题标题】:Where should I do Injection with Ninject 2+ (and how do I arrange my Modules?)我应该在哪里使用 Ninject 2+ 进行注入(以及如何安排我的模块?)
【发布时间】:2010-12-01 07:50:40
【问题描述】:

我有两个相关(与这个问题相关的)项目和其他几个项目的解决方案;

  1. 具有其他几个项目使用的功能的类库。
  2. ASP.NET MVC 应用程序。

我的问题基本上是我应该在哪里使用 Ninject 2 进行 IoC,考虑到...

  • 类库需要一些 DI 的喜爱,其中包括需要 Web 请求特定会话对象的存储库类(想想工作单元)。
  • MVC 应用需要 DI,因为在 Ninject 2 中,您基本上从 NinjectHttpApplication 继承。
  • 类库的单元测试需要意识到这一点,才能注入一组不同的存储库。
  • 出于同样的原因,需要注入 Web 应用的单元测试。

我在这里把自己描绘成一个心理角落,因为我一开始只看到了三个选项。类库中的 DI,Web 应用程序中的 DI,或两者都有,但每个都有问题:

  • 我不能只在类库中进行 DI,因为 MVC 应用需要从 NinjectHttpApplication 继承。
  • 我不能只在 MVC 应用程序中进行 DI - 毕竟类库被其他库使用,而且 MVC 应用程序不应该对库的内部了解太多。
  • 我想这是我能看到的唯一出路:两个项目的独立 IoC。类库和 MVC 应用都有自己的 IoC 设置,并为他们的东西做 DI,而不是真正关心彼此。

有没有人有一些“最佳做法”或指导方针来说明如何做这样的事情?我无法想象我是第一个遇到这种情况的人,很高兴知道这样做的“正确”方法是什么......

谢谢!

【问题讨论】:

标签: asp.net-mvc inversion-of-control ninject


【解决方案1】:

我不知道 NInject,但除非它的工作方式与 Windsor、StructureMap 等有很大不同。答案往往保持不变,因为有一些常见的 DI 模式。考虑到这一点:

首先要意识到的是,DI 并不依赖于特定的框架,例如 NInject 或 Windsor。它是一组要遵循的技术和设计模式。您可以使用所谓的 Poor Man's DI 手动执行 DI,但显然使用 DI Container 会更好。

为什么这是相关的?这是相关的,因为一旦您意识到这一点,推论就是您的应用程序的绝大多数代码应该了解 DI 容器什么的。

那么您在哪里使用 DI 容器?它只能用于 Composition Root,在您的情况下,它对应于 Global.asax。您可以在 this SO answer 中阅读更多相关信息 - 虽然这个问题是关于温莎的,但原理保持不变。

那么你的单元测试呢?他们也应该完全不知道 DI Container。详情请见this other SO answer

DI 可以通过大量使用构造函数注入 在您的库中实现。您不需要引用任何 DI 容器来执行此操作,但是如果您使用 DI 容器来解决来自合成根的所有依赖项,它会使生活变得更加轻松。

【讨论】:

  • 嗨,马克 - 感谢您的回答,我想我现在明白了,至少大部分时间都明白了。但是,如果 MVC / Global.asax 负责设置所有 DI,它是否也需要插入类库的东西?考虑到类库可能需要存储每个 web 请求的 ISession 或类似的东西,它将用于构造所有存储库类。 MVC 应用程序应该知道这一点吗?只是试图围绕“正确的事情”去做。 :)
  • 由于您使用的是 MVC,因此最好的选择是使用自定义 ControllerFactory 来创建具有所有依赖项的控制器。您可以在 MvcContrib 源代码中看到一个使用 Windsor 的示例:github.com/mvccontrib/MvcContrib/blob/… 如果某些依赖项是库中的类型,则这些依赖项应由控制器导入。如果您需要将 ISession 实例传递给您的库,您可以使用控制器的 ctx 来执行此操作 - 它已经由您的自定义工厂设置。
  • 再次感谢,马克。我得试一试——我猜,没有什么比实际做事更好的了。 Ninject 是基于模块的,因此我可以在我的类库中创建一个单独的模块,该模块也被 MVC 应用程序中的 IoC 设置自动使用,我只需要尝试一下。非常感谢!
  • 我目前正在使用本地版本的依赖解析器,并希望切换到流行的框架之一。我当前的方法将业务程序集中的所有具体类都标记为内部。要将 DI 容器保留在 Global.asax 中,我必须公开我的具体类,以便解决它们,对吗?是否有另一种方法可以将 DI 容器保留在组合根目录中,同时直接隐藏(或至少防止实例化)我的具体类?附言我尝试在您的博客上发布此内容,但出现错误。
  • 是的,您需要公开这些课程。这在任何情况下都是合适的,因为 DI 的基本目的是松散耦合,因此是可维护性的。这意味着您希望设计良好的类保持可维护性,如果您有,就没有理由将它们隐藏起来。在任何情况下,接口也可以起到一定的绝缘作用:blog.ploeh.dk/2011/02/28/InterfacesAreAccessModifiers.aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 2022-06-18
  • 1970-01-01
  • 2018-09-04
  • 2017-08-25
  • 1970-01-01
相关资源
最近更新 更多