ASP.NET Core的依赖注入
一、什么是依赖注入?
1、DI是什么?
DI是一种软件设计模式,是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术,故而在业界被称之为:依赖关系注入。千万不要被其名唬住了,以为是多么深不可测的东西!
2、IoC又是什么?
官方的说法:大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果模块 A 调用模块 B 中的函数,而模块 B 又调用模块 C 中的函数,则编译时 A 取决于 B,而 B 又取决于 C!
应用依赖关系反转原则后,A 可以调用 B 实现的抽象上的方法,让 A 可以在运行时调用 B,而 B 又在编译时依赖于 A 控制的接口,这时,典型的编译时依赖项就发生了反转,也就是所谓的控制反转(IoC)!
二、ASP.NET Core依赖注入的实现
1、什么是依赖项?
依赖项是指另一个对象所依赖的对象。 如:我们创建一个简单的类Hello
public class Hello
{
public string WriteMessage()
{
return "Hello,Weclome To Use ASP.NET Core";
}
}
类可以创建 Hello 类的实例,以便利用其 WriteMessage 方法,这时也就产生了依赖。
public class HelloController : Controller
{
private readonly Hello _hello = new Hello();
public string WriteMessage()
{
return _hello.WriteMessage();
}
}
2、依赖项解藕
上述代码中,导致了一个严重的问题:该类创建并直接依赖于 Hello 类。 因为在应用中,应避免使用,原因如下:
(1)、要用不同的实现替换 Hello,必须修改 HelloController类
(2)、如果 Hello 具有依赖项,则必须由 HelloController 类对其进行配置。 在具有多个依赖于 Hello 类的大型项目中,配置代码将分散在整个应用中。
(3)、这种实现很难进行单元测试。 应用需使用模拟或存根 Hello 类,而该类不能使用此方法。
IHello接口定义如下:
public interface IHello
{
public string WriteMessage();
}
此接口由具体类型 Hello 实现:
public class Hello : IHello
{
public string WriteMessage()
{
return "Hello,Weclome To Use ASP.NET Core";
}
}
2、依赖关系注入服务
通过依赖关系注入可以解决:
(1)、使用接口或基类将依赖关系实现抽象化
(2)、在服务容器中注册依赖关系。
(3)、将服务注入到使用它的类的构造函数中。
容器负责创建依赖关系的实例,并在不再需要时将其释放
在Startup.cs的ConfigureServices中为 Hello 注册服务生存期如下:
改造HelloController,请求 IHello 服务并用于调用 WriteMessage 方法,这时整个依赖注入过程就已全部完成!
public class HelloController : Controller
{
private readonly IHello _hello;
public HomeController(IHello hello)
{
_hello = hello;
}
public IActionResult Index()
{
ViewBag.Msg = _hello.WriteMessage();
return View();
}
}
三、依赖注入的体现
现在我们来模拟这样一个场景:我们想IHello的WriteMessage不再输出Hello,Weclome To Use ASP.NET Core,而是输出Hello,Weclome To Use Micrsoft Visual Suodio ,但同时要保留Hello,Weclome To Use ASP.NET Core的输出是可用的。就好像:以前企业的支付是通过银联的,现在要换成微信支付,同时要保留原来的银联支付的可用的场景是一样的。假如没有进行依赖注入的话,通常我们的第一反应:重新new,IHello就可以了!
但面对企业大型的代码,涉及到的成千上万相关代码都要修改,你得new多少?new完了你还有心思和时间去开展新的工作吗?而这时候,我们通过依赖注入的话,完全不需要更改任何的代码,只需要在服务中,注册新的服务即可!
public class HelloController : Controller
{
private readonly IHello _hello;
public HomeController(IHello hello)
{
_hello = hello;
}
public IActionResult Index()
{
ViewBag.Msg = _hello.WriteMessage();
return View();
}
}
而此时WriteMessage,已由Hellos来执行,不再是以前的Hello,一行代码,就高效便捷的解决了我们新的需求,即:将银联支付的注入更换成微信支付注入,同时仍然完整的保留了原来的银联支付,这就是依赖注入(DI)设计模式IoC反转的魅力!
public class Hellos : IHello
{
public string WriteMessage()
{
return "Hello,Weclome To Use Micrsoft Visual Suodio";
}
}