DI容器如何工作的最简单解释?

12 dependency-injection inversion-of-control

简单来说和/或高级伪代码,DI容器如何工作以及如何使用?

Fin*_*las 5

它只不过是一个奇特的对象哈希表。

虽然上面的说法是一种轻描淡写的说法,但这是思考它们的简单方法。给定集合,如果您请求类的相同实例 - DI 容器将决定是否为您提供缓存版本或新版本,等等。

当涉及到连接依赖项时,它们的使用使得它变得更容易和更清晰。假设您有以下伪类。

class House(Kitchen, Bedroom)
     // Use kitchen and bedroom.
end

class Kitchen()
    // Code...
end

class Bedroom()
   // Code...
end
Run Code Online (Sandbox Code Playgroud)

如果没有 DI 容器,建造房子会很痛苦,您需要创建一个卧室的实例,然后创建一个厨房的实例。如果这些对象也具有依赖关系,则需要将它们连接起来。反过来,您可能会花费许多行代码来连接对象。只有这样你才能建造一座有效的房子。使用 DI/IOC(控制反转)容器,您说想要一个房屋对象,DI 容器将递归地创建其每个依赖项并返回一个房屋。

没有 DI/IOC 容器:

house = new House(new Kitchen(), new Bedroom());
Run Code Online (Sandbox Code Playgroud)

使用 DI/IOC 容器:

house = // some method of getting the house
Run Code Online (Sandbox Code Playgroud)

最终,它们使代码更易于理解、更易于编写,并将将对象连接在一起的责任从手头的问题转移开。


Mar*_*ann 5

DI Container的核心是根据接口和具体类型之间的映射创建对象.

这将允许您从容器中请求抽象类型:

IFoo f = container.Resolve<IFoo>();
Run Code Online (Sandbox Code Playgroud)

这要求您先前已将容器配置为从IFoo映射到实现IFoo的具体类(例如Foo).

这本身并不会特别令人印象深刻,但DI Containers做得更多:

  • 他们使用Auto-Wiring意味着他们可以自动判断如果IFoo映射到Foo并且IBar映射到Bar,但是Foo依赖于IBar,它会在您请求IFoo时创建带有Bar的Foo实例.
  • 他们管理组件的生命周期.你们每次都想要一个新的Foo实例,但在其他情况下你可能需要相同的实例.您甚至可能每次都想要新的Foo实例,但注入的Bar应保持相同的实例.

一旦你开始尝试手动管理组合生命周期,你应该开始欣赏DI容器提供的服务:)

许多DI容器可以做到比上面更多,但那些是核心服务.大多数容器提供通过代码或XML进行配置的选项.

在正确使用容器方面,Krzysztof Kozmic刚刚发表了一篇很好的概述.