反对控制容器反转的论据

viv*_*vri 31 ioc-container inversion-of-control

似乎每个人都在转向IoC容器.我曾试图"摸清"它一段时间,尽管我不想成为一个在高速公路上走错路的司机,但它仍然没有通过常识测试.让我解释一下,如果我的论点存在缺陷,请纠正/启发我:

我的理解:IoC容器应该在组合不同组件时让您的生活更轻松.这可以通过a)构造函数注入,b)setter注入和c)界面注入来完成.然后以编程方式或在容器读取的文件中"连接"它们.然后按名称召唤组件,然后在需要时手动投射.

我得不到的:

编辑 :( 更好的措辞) 为什么使用一个不是语言惯用的不透明容器,如果组件设计得当(使用IoC模式,松散耦合),你可以用更简洁的方式"连接"应用程序(imho) ?这个"托管代码"如何获得非平凡的功能?(我听过一些关于生命周期管理的提及,但我不一定能理解这比自己动手更好/更快.)

ORIGINAL:为什么要将所有组件存储在一个容器中,以与语言惯用的方式"连接起来",在按名称调用组件时使用相当于"goto labels"的东西,然后通过手动转换失去静态类型语言的许多安全优势,当你通过不执行它获得等效功能时,而是使用现代OO语言给出的所有很酷的抽象功能,例如编程到接口?我的意思是,实际上需要使用组件的部件必须知道它们在任何情况下都在使用它,并且在这里你将使用最自然,惯用的方式进行"连线" - 编程!

Mar*_*ann 62

当然有人认为DI容器没有任何好处,这个问题是有效的.如果你纯粹从物体成分角度看它,容器的好处可能看起来微不足道.任何第三方都可以连接松散耦合的组件.

但是,一旦你超越玩具场景,你应该意识到连接合作者的第三方必须承担更多简单的构图责任.也可能存在退役问题以防止资源泄漏.由于作曲家是唯一知道某个实例是共享实例还是私有实例的一方,因此它还必须承担执行生命周期管理的角色.

当您开始组合各种实例范围,使用共享和私有服务的组合,甚至可能将某些服务范围限定到特定上下文(例如Web请求)时,事情变得复杂.用穷人的DI编写所有代码当然是可能的,但它不会增加任何商业价值 - 它是纯粹的基础设施.

此类基础结构代码构成通用子域,因此创建可重用库以解决此类问题非常自然.这正是DI Container的意义所在.

顺便说一句,我所知道的大多数容器都没有使用名称来连接它们 - 它们使用自动布线,它将构造函数注入的静态信息与容器从接口到具体类的映射配置相结合.简而言之,容器本身就能理解这些模式.

DI不需要DI容器 - 它只是该死的有用.


更详细的处理可以在文章何时使用DI容器中找到.


Dav*_*vid 7

我确信在这个问题上有很多话要说,希望我能编辑这个答案以便以后添加更多(希望更多的人会添加更多的答案和见解),但只需要几个快速点到你的帖子.. .

使用IoC容器是控制反转的一个子集,而不是整个事物.您可以使用控制反转作为设计构造,而不依赖于IoC容器框架.最简单的是,在这种情况下,可以将控制反转称为"供应,不实例化".只要你的对象在内部不依赖于其他对象的实现,而是要求为它们提供实例化的实现,那么你就是使用控制反转.即使您没有使用IoC容器框架.

关于编程到接口的问题......我不确定你对IoC容器的体验是什么(我个人最喜欢的是StructureMap),但你绝对可以编程到IoC接口.至少在我如何使用它的过程中,整个想法是将接口(类型)与实现(注入的类)分开.依赖于接口的代码仅被编程为那些,并且在需要时注入这些接口的实现.

例如,您可以IFooRepository从类型的数据存储实例返回Foo.所有需要这些实例的代码都从提供的类型对象中获取它们IFooRepository.在其他地方,您可以创建一个实现FooRepository并配置您的IoC,以便随时随地IFooRepository提供.这个实现可以从数据库,XML文件,外部服务等获取它们.无论在哪里.这种控制已被颠倒过来.使用类型对象的代码Foo并不关心它们来自何处.

显而易见的好处是,您可以随时更换该实现.您可以将其替换为测试版本,根据环境更改版本等.但请记住,您在任何给定时间也不需要具有这样的1:1比例的接口.

例如,我曾经在之前的工作中使用过代码生成工具,它将大量的DAL代码吐出到一个类中.将它拆开可能是一种痛苦,但是没有太大的痛苦就是将它配置为在特定的方法/属性名称中吐出所有内容.所以我为我的存储库编写了一堆接口,并生成了一个实现所有这些接口的类.对于那个生成的类,它很难看.但我的应用程序的其余部分并不关心,因为它将每个接口视为自己的类型.IoC容器为每个容器提供了相同的类.

我们能够快速启动并运行,没有人在等待DAL开发.虽然我们继续使用使用接口的域代码,但是初级开发人员的任务是创建更好的实现.后来交换了这些实现,一切都很顺利.

正如我之前提到的,这可以在没有IoC容器框架的情况下完成.这个模式本身很重要,真的.