似乎每个人都在转向IoC容器。我曾试图“摸清”它一段时间,尽管我不想成为高速公路上错误方向的一个司机,但它仍然没有通过常识测试。让我解释一下,如果我的论点存在缺陷,请纠正/启发我:
我的理解:IoC容器应该在组合不同组件时让您的生活更轻松。这可以通过a)构造函数注入,b)setter注入和c)界面注入来完成。然后以编程方式或在容器读取的文件中“连接”它们。然后按名称召唤组件,然后在需要时手动投射。
我没有得到:
编辑:(更好的措辞) 为什么要使用一个对语言来说不是惯用的不透明容器,如果组件设计得当(使用IoC模式,松散耦合),你可以用更简单的方式“连接”应用程序(imho)?这个“托管代码”如何获得非平凡的功能? (我听过一些关于生命周期管理的提及,但我不一定能理解这比自己动手更好/更快。)
ORIGINAL : 为什么要将所有组件存储在一个容器中,以与语言惯用的方式“连接起来”,在按名称调用组件时使用相当于“goto labels”的东西,然后丢失许多组件通过手动转换获得静态类型语言的安全优势,当您通过不执行它获得等效功能时,而是使用现代OO语言给出的所有很酷的抽象功能,例如:编程到接口?我的意思是,实际上需要使用组件的部件必须知道它们在任何情况下都在使用它,并且在这里你将使用最自然,惯用的方式进行“连线” - 编程!
答案 0 :(得分:59)
肯定有people who think that DI Containers add no benefit,问题是有效的。如果你纯粹从物体成分角度看它,容器的好处可能看起来微不足道。任何第三方都可以连接松散耦合的组件。
然而,一旦你超越了玩具场景,你应该意识到连接合作者的第三方必须承担更多简单的构图责任。也可能存在退役问题以防止资源泄漏。由于作曲家是唯一知道某个实例是共享还是私有的人,因此它还必须扮演终身管理的角色。
当您开始组合各种实例范围,使用共享和私有服务的组合,甚至可能将某些服务范围限定到特定上下文(例如Web请求)时,事情变得复杂。用穷人的DI编写所有代码当然是可能的,但它不会增加任何商业价值 - 它是纯粹的基础设施。
此类基础架构代码构成通用子域,因此创建可重用库以解决此类问题非常自然。这正是DI Container的意思。
BTW,我所知道的大多数容器都不使用名称来连接它们 - 它们使用自动连接,它将构造函数注入的静态信息与容器从接口到具体类的映射配置相结合。简而言之,容器本身就能理解这些模式。DI不需要DI容器 - 它只是该死的有用。
更详细的处理可以在文章When to use a DI Container中找到。
答案 1 :(得分:7)
我确信在这个问题上有很多话要说,希望我能编辑这个答案以便以后添加更多(希望更多的人会添加更多的答案和见解),但只需要几个快速点交...
使用IoC容器是inversion of control的子集,而不是整个事件。您可以使用控制反转作为设计构造,而不依赖于IoC容器框架。最简单的是,在这种情况下,可以将控制反转称为“供应,不实例化”。只要你的对象在内部不依赖于其他对象的实现,而是要求为它们提供实例化的实现,那么你就是使用控制反转。即使您没有使用IoC容器框架。
关于编程到接口的问题...我不确定你对IoC容器的体验是什么(我个人最喜欢的是StructureMap),但你肯定会编程到IoC的接口。至少在我如何使用它的过程中,整个想法是将接口(类型)与实现(注入的类)分开。依赖于接口的代码仅被编程为那些,并且在需要时注入这些接口的实现。
例如,您可以从IFooRepository
类型的数据存储实例返回Foo
。您需要这些实例的所有代码都从类型为IFooRepository
的提供对象中获取它们。在其他地方,您创建了FooRepository
的实现,并将IoC配置为在需要IFooRepository
的任何地方提供。这个实现可以从数据库,XML文件,外部服务等获取它们。无论在哪里。这种控制已被颠倒过来。使用Foo
类型对象的代码并不关心它们来自何处。
显而易见的好处是,您可以随时更换该实现。您可以将其替换为测试版本,根据环境更改版本等。但请记住,您在任何给定时间也不需要具有这样的1对1比例的接口。
例如,我曾经在之前的工作中使用过代码生成工具,它将大量的DAL代码吐出到一个类中。将它拆开可能是一种痛苦,但是没有太大的痛苦就是将它配置为在特定的方法/属性名称中吐出所有内容。所以我为我的存储库编写了一堆接口,并生成了一个实现 all 的类。对于那个生成的类,它很难看。但我的应用程序的其余部分并不关心,因为它将每个接口视为自己的类型。 IoC容器为每个容器提供了相同的类。
我们能够快速启动并运行,没有人在等待DAL开发。虽然我们继续使用使用接口的域代码,但是初级开发人员的任务是创建更好的实现。这些实现后来被交换了,一切都很好。
正如我前面提到的,这可以在没有IoC容器框架的情况下完成。真正的模式本身很重要。
答案 2 :(得分:2)
首先是什么是IOC?这意味着创建依赖对象的责任将从主对象中删除并委派给第三方框架。我总是使用spring作为我的IOC框架,它带来了很多好处。
促进编码与接口和解耦 - 关键的好处是IOC促进并使解耦变得非常容易。您始终可以在主对象中注入接口,然后使用接口方法执行任务。主对象不需要知道哪个依赖对象被分配给接口。当您想要使用不同的类作为依赖项时,您只需要在配置文件中将旧类交换为新类,而无需更改一行代码。现在您可以争辩说,这可以使用各种界面设计模式在代码中完成。但是IOC框架让它在公园散步。因此,即使作为新手,您也可以成为掌握桥梁,工厂等各种界面设计模式的专家。
清洁代码 - 由于大多数对象创建和对象生命周期操作都委托给IOC容器,因此您可以从写入肉鸡点重复代码中保存。所以你有一个更干净,更小,更容易理解的代码。
单元测试 - IOC使单元测试变得简单。由于您只需要解耦代码,因此可以轻松地单独测试解耦代码。您还可以轻松地在测试用例中注入依赖项,并查看不同组件的交互方式。
属性配置程序 - 几乎所有应用程序都有一些属性文件,用于存储特定于应用程序的静态属性。现在要访问这些属性,开发人员需要编写包装器,它将读取和解析属性文件,并以应用程序可以访问的格式存储属性。现在,所有IOC框架都提供了在特定类中注入静态属性/值的方法。所以这又成了在公园散步。
这些是我能立即思考的一些观点,我相信还有更多。