【发布时间】:2012-03-02 09:42:49
【问题描述】:
谁能帮助我用简单的 C# 示例来理解 DI 和 IOC 吗?据我了解,IOC 是控制流的反转(这对我来说毫无意义),而 DI 意味着通过属性或构造函数注入接口。不知道这两者有什么关系。
谢谢。
【问题讨论】:
标签: c# design-patterns
谁能帮助我用简单的 C# 示例来理解 DI 和 IOC 吗?据我了解,IOC 是控制流的反转(这对我来说毫无意义),而 DI 意味着通过属性或构造函数注入接口。不知道这两者有什么关系。
谢谢。
【问题讨论】:
标签: c# design-patterns
我强烈推荐你阅读Dependency Injection in .NET这本书,它通过全面的代码示例详细描述了各个方面。对于控制反转,您应该参考 Robert Martin 的另一本书:Agile Principles, Patterns, and Practices in C#。它通过示例和易于理解的解释详细描述了 SOLID 原理。这两本书确实帮助我理解了这些原则。
【讨论】:
假设您有一个需要服务的类:
public class A
{
IEmailSender _emailSender
public A(IEmailSender emailSender)
{
_emailSender = emailSender;
}
private void SendEmail()
{
_emailSender.Send();
}
}
类 A 现在据说依赖于 IEMailSender,这意味着它需要一个实现 IEMailSender 的对象才能执行其功能。
像 ninject 或 autofac 这样的依赖注入框架将负责创建一个实现 IEMailSender 的对象并将其注入到 A 的构造函数中,前提是您告诉他们如何创建这样的对象。 p>
前使用ninject:
Bind<IEmailSender>().To<EmailSender>();
这是在告诉 ninject,每当一个类需要一个 IEMailSender 时,就给他们 EmailSender(当然假设 EmailSender 实现了 IEMailSender 接口)
这是我能想到的最简单的方法,希望对您有所帮助。
【讨论】:
DI 是 IoC。控制反转意味着交换谁来决定如何完成任务。
在旧世界中,您可能会创建一个名为 Logger 的类,并在该类中创建一个名为 LogTime() 的方法。它的唯一目的是将当前时间写入文件。
public void LogTime()
{
WriteToFile(GetCurrentTime());
}
这里的类有一个名为WriteToFile 和GetCurrentTime 的方法。 IoC 只是意味着您可以让外部提供者提供这些详细信息,而不是由 Logger 类决定如何写入文件,甚至获取当前时间。
这就是 DI 的用武之地。您注入了一个依赖项。该方法取决于写入文件和获取当前时间的方法。你注入这些方法。
DI 有两种常见的模式,即属性注入和构造函数注入。他们按照锡上所说的去做。具体方式取决于执行注入的特定框架。
有些使用属性,有些使用配置文件。有些人采用最佳猜测方法。
除了 DI,还有 SL(服务位置),就像礼貌的 DI。在 DI 中,您说“接受这种依赖并喜欢它”。使用 SL,上面的 Logger 类会说“是否有可能有一些东西来填补这种依赖关系??”。看?礼貌。
使其工作的核心是接口。 LogToFile 可能是 ILogsToFiles 接口上的一个方法。然后,您可以拥有该接口的六种不同实现并注入最合适的实现。
有很多可用的框架可以为您管理所有这些,但是一个简单的 ServiceLocator 是 10 行代码,一个简单的 DI 可能不会超过两倍。不过,您很快就会开始想要额外的东西。看看宁杰。我推荐它纯粹是因为它小而简单,可能是一个很好的起点。
【讨论】:
我将添加一个解释,我被告知这是一个有用的解释。
正如您正确指出的那样,依赖注入是类通过构造函数或设置器注入要求其协作者的行为。您可以将其视为一种编码技术。另一方面,控制反转更像是一种设计技术——一种哲学,如果你愿意的话。
在过程式编程(以及面向对象语言中的过程式编程)中,您通常具有某种“命令和控制”理念。如果您正在创建一个包含三个楼层对象的房屋对象,每个楼层对象包含一定数量的房间对象,您将创建一个房屋对象,其构造函数实例化三个楼层对象,而每个楼层对象的构造函数依次实例化房间对象。
当您颠倒控制时,您就是在颠倒命令和控制范式。使用 IoC,当我去实例化房子时,它不会为我处理所有细节。相反,它说,通过它的构造函数(和依赖注入),“你不能在没有一些楼层的情况下实例化我”。所以,你去实例化地板,他们说“不,不是没有一些房间”。现在,在这种“倒置”的风格中,我们的房子不控制房间的创建——它把它留给其他人,它只表达了它会对给定的房间做什么。这是可取的,因为通过翻转命令和控制,您可以更好地推理和测试代码——将事物解构为组件更容易。
因此,总而言之,控制反转是一种哲学,而依赖注入是实现它的手段。
【讨论】: