【发布时间】:2011-06-08 23:05:09
【问题描述】:
【问题讨论】:
标签: asp.net-mvc dependency-injection
【问题讨论】:
标签: asp.net-mvc dependency-injection
依赖注入是向消费代码提供依赖而不是负责实例化对象本身的代码的过程。在一个原始示例中,您可能有一个类负责计算所提供服务的发票。你实例化它并调用它的“计算”方法:
public class InvoiceBiller
{
public void Bill()
{
Calculator calculator = new Calculator();
var totalAmountDue = calculator.CalculateBill(hoursWorked);
}
}
此方法依赖于 Calculator 类。没关系,它有效。然而依赖注入会让你“注入”计算器依赖:
public class InvoiceBiller
{
private readonly Calculator calculator;
public InvoiceBiller(Calculator calculator)
{
this.calculator = calculator;
}
public void Bill()
{
var totalAmountDue = calculator.CalculateBill(hoursWorked);
}
}
正如您在第二个示例中看到的那样,InvoiceBiller 类通过其构造函数(一种称为构造函数注入的依赖注入形式)被赋予了一个 Calculator 对象。 InvoiceBiller 不再关心如何获取 biller 的实例,它只是简单地给出一个。
这有助于测试。您可以从测试中传递您想要的任何计算器实例。在实际产品的运行时,您可以传入一个连接到数据库并查找小时费率的计算器。对于测试,您传入一个使用硬编码率的计算器,这样您的测试就不需要访问数据库。
更进一步,您通常会传入接口而不是具体类型:
public class InvoiceBiller
{
private readonly ICalculator calculator;
public InvoiceBiller(ICalculator calculator)
现在您正在针对接口而不是实现进行编程。再次从您的测试中,您可以使用模拟框架来创建您的接口类型的模拟并将它们传递给类。
【讨论】:
其实这里有两个问题。有“什么是依赖注入?”和“MVC 3 中‘添加更多’依赖注入支持的新功能是什么?”。
依赖注入是一种编程模式,当类在使用它们之前没有定义其他类的新对象(例如需要在 DB 中记录电子邮件的某些 Email Sender 类不会创建新的 Logger 实例),但请求它在不知道它可能是哪个类的情况下提供(使用接口,在我们的例子中说 ILogger)。这里的记录器将是一个依赖项,并且通过多种方式请求/注入此依赖项,或者作为依赖类的构造函数参数请求(例如,EmailSender),或者只是将其作为类“set”访问器的属性,等等……
有一些库称为依赖注入库或控制容器反转。在这些库中,您可以定义在运行时真正应该使用哪些类以及要使用哪些其他特定值,并告诉它们为您创建对象(例如创建 EmailSender 的实例),递归地将所有依赖项传递给它们(因此,如果 ILogger 实际上是一个需要连接字符串的 DBLogger,它也会发送它,等等。)。例如 Windsor、Ninject、Autofac、Microsoft Unity、...
有关示例代码和更清晰的示例,请观看这个曾经在 ASP.NET MVC 团队工作的人提供的精彩免费视频:
http://tekpub.com/view/concepts/1
ASP.NET MVC 始终允许一个工厂类,您可以在其中覆盖控制器类的创建方式(这样您就可以使用 DI 容器库来创建控制器及其依赖项,就像它或 EmailSender 类一样)。 ASP.NET MVC 3.0 带来的是对现有功能的改进,并提供了更多类似的方法,以便更容易在 ASP.NET MVC 上进行 DI
和
查看它们以了解详细信息...
【讨论】:
可能更适合程序员,但首先要了解控制反转
http://en.wikipedia.org/wiki/Inversion_of_control
http://www.martinfowler.com/articles/injection.html
这个想法是组件不应该知道如何获取/创建其依赖项,应该提供完成工作所需的内容。
【讨论】: