我该在哪里使用Ninject 2+ 进行注入(以及如何安排我的模块)?

39
我有两个相关项目(与此问题有关),以及其他几个项目:
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。
是否有人对如何解决这类问题有一些“最佳实践”或指南?我无法想象我是第一个遇到这种情况的人,如果知道“正确”的方法,那肯定是很好的...
谢谢!

1
相关:https://dev59.com/qW435IYBdhLWcg3wtCSQ - Ruben Bartelink
1
重复,但有一些值得挖掘的评论,如果你真的想要完整的见解。https://dev59.com/GVbTa4cB1Zd3GeqP-Wrg - Ruben Bartelink
1个回答

64

我不了解NInject,但是除非它的工作方式与Windsor、StructureMap等有很大不同,否则答案往往都是相同的,因为有一些常见的依赖注入(DI)模式。基于此:

首先要认识到的是,DI并没有与特定的框架(如NInject或Windsor)绑定。它是一组应该遵循的技术和设计模式。你可以使用所谓的“贫民版”DI手动执行DI,但显然使用DI容器更好。

这有何关联?这很重要,因为一旦你认识到这一点,必然会得出这样的推论:应用程序代码的绝大部分都不应该知道DI容器。

那么在哪里使用DI容器呢?它应该仅在组合根 中使用,在你的情况下对应于Global.asax。你可以在这个SO答案中了解更多 - 尽管这个问题是关于Windsor的,但原则仍然是一样的。

那么你的单元测试呢?它们也应该完全不知道DI容器。请参见这个SO答案以获取更多详细信息。

在你的库中可以通过大量使用构造函数注入来实现DI。你不需要引用任何DI容器来做到这一点,但如果你使用DI容器从组合根解析所有依赖关系,那么生活会变得更轻松。


嗨,马克 - 感谢你的回答,我现在明白了,至少大部分明白了。然而,如果MVC / Global.asax负责设置所有DI,它是否还需要查看类库内容?考虑到类库可能需要存储每个Web请求的ISession或类似的东西,这将用于构建所有存储库类。MVC应用程序需要知道这一点吗?只是试图理解“正确的事情”要做的事情。 :) - Rune Jacobsen
1
由于您正在使用MVC,最好的选择是使用自定义ControllerFactory来创建具有所有依赖项的控制器。您可以在MvcContrib源代码中看到Windsor的示例:http://github.com/mvccontrib/MvcContrib/blob/be0eb3addedf1775db719117e7fa73e516f74c8d/src/MvcContrib.Castle/WindsorControllerFactory.cs 如果某些依赖项是库中的类型,则应该由Controller导入。如果您需要将ISession实例传递给库,则可以使用Controller的ctx来完成这一点-它已经由您的自定义工厂设置好了。 - Mark Seemann
再次感谢,马克。我得试一试-我想没有什么比真正去做更好了。Ninject是基于模块的,所以我可以在我的类库中创建一个单独的模块,这个模块会被MVC应用程序中的IoC设置自动使用。我只需尝试一下。非常感谢! - Rune Jacobsen
我目前正在使用自制的依赖解析器,并希望切换到一种流行的框架。我的当前方法将业务程序集中的所有具体类标记为内部。为了保持DI容器在Global.asax中,我必须公开我的具体类以便它们可以被解析,对吗?是否有另一种方法可以将DI容器保留在组合根中,同时隐藏(或至少防止直接实例化)我的具体类?附言:我尝试在您的博客上发布此内容,但出现错误。 - adam0101
1
是的,您需要将类设置为公共类。无论如何,这是适当的,因为DI的根本目的是松耦合,从而实现可维护性。这意味着您希望设计良好的类保持可维护性,如果您做到了这一点,就没有理由将它们隐藏起来。无论如何,接口也充当一层隔离层:http://blog.ploeh.dk/2011/02/28/InterfacesAreAccessModifiers.aspx - Mark Seemann
结果是,你的应用程序代码的绝大部分都不应该对 DI 容器有任何了解。+1。 - user1496062

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接