ASP.NET Core中IOC容器的实现原理
首先我们需要了解什么是IOC,为什么要使用IOC容器?
一、依赖
using System;
namespace MyIOCDI
{
public class Test
{
public void Show()
{
MyDependency myDependency = new MyDependency(); //全是细节
myDependency.Show();
Console.WriteLine($"This is {this.GetType().FullName}");
}
}
public class MyDependency
{
public void Show()
{
Console.WriteLine($"This is {this.GetType().FullName}");
}
}
}
上面的示例中,Test类就依赖了MyDependency类。
二、依赖倒置原则(Dependence Inversion Principle)
高层模块不应该依赖于低层模块,二者都应该依赖于抽象,而不是依赖细节。
什么是高层模块?这里的使用者Test类就称为高层模块。
什么是低层模块?被使用者MyDependency类就称为低层模块。
上面的示例中我们的高层模块就依赖于我们的低层模块。
那么这样子有什么不好呢?
1、面向对象语言开发,就是类与类之间进行交互,如果高层直接依赖低层的细节,细节是多变的,那么低层的变化就导致上层的变化;
2、如果层数多了,低层的修改会直接水波效应传递到最上层,一点细微的改动都会导致整个系统从下往上的修改。
因此,上例按照依赖倒置原则修改如下:
using System;
namespace MyIOCDI
{
public class Test
{
public void Show()
{
IDepenency myDependency = new MyDependency(); //左边抽象右边细节
myDependency.Show();
Console.WriteLine($"This is {this.GetType().FullName}");
}
}
public class MyDependency : IDepenency
{
public void Show()
{
Console.WriteLine($"This is {this.GetType().FullName}");
}
}
public interface IDepenency
{
void Show();
}
}
interface补充
interface是面向对象编程语言中接口操作的关键字,功能是把所需成员组合起来,用来封装一定功能的集合。它好比一个模板,在其中定义了对象必须实现的成员,通过类或结构来实现它。接口不能直接实例化,即ICount ic=new iCount()是错的。接口不能包含成员的任何代码,只定义成员本身。接口成员的具体代码由实现接口的类提供。接口使用interface关键字进行声明。
三、IOC控制反转
控制反转是一种思想,所谓“控制反转”就是反转获得依赖对象的过程。
上面示例经过改造后虽然遵循了“依赖倒置原则”,但是违背了“开放封闭原则”,因为如果有一天想要修改变量myDependency为YourDependency类的实例,则需要修改Test类。
因此,我们需要反转这种创建对象的过程:
using System;
namespace MyIOCDI
{
public class Test
{
private readonly IDepenency _myDependency;
public Test(IDepenency myDependency)
{
this._myDependency = myDependency;
}
public void Show()
{
_myDependency.Show();
Console.WriteLine($"This is {this.GetType().FullName}");
}
}
public class MyDependency : IDepenency
{
public void Show()
{
Console.WriteLine($"This is {this.GetType().FullName}");
}
}
public interface IDepenency
{
void Show();
}
}
上例中,将 _myDependency 的创建过程“反转”给了调用者。
四、依赖注入(Dependency Injection) 依赖注入是一种在类及其依赖对象之间实现控制反转(IOC)思想的技术。
所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
依赖注入就是能做到构造某个对象时,将依赖的对象自动初始化并注入 。
IOC是目标是效果,需要依赖注入的手段。
三种注入方式:构造函数注入--属性注入--方法注入(按时间顺序)
构造函数注入用的最多,默认找参数最多的构造函数,可以不用特性,可以去掉对容器的依赖。
IOC容器的Unity的使用作用介绍
1.Unity支持简单对象创建,特别是分层对象结构和依赖,以简化程序代码。其包含一个编译那些可能存在依赖于其他对象的对象实例机制。
2.Unity支持必要的抽象,其允许开发者在运行时或配置去指定依赖关系同时可以简单的管理横切点(AOP)。
3.Unity增加了推迟到容器组件配置的灵活性。其同样支持一个容器层次的结构。
4.Unity拥有服务定位能力,对于一个程序在许多情况下重复使用组件来分离和集中功能是非常有用的。
5.Unity允许客户端储存或缓存容器。对于在ASP.NET Web applications中开发者将容器持久化于ASP.NET中的session或application中特别有效。
6.Unity拥有拦截能力,其允许开发者通过创建并执行handlers(在方法或属性被调用到达之前)来为已存在的组件增加一个函数,并再次为返回调用结果。
7.Unity可以从标准配置系统中读取配置信息,例如:XML文件,同时使用配置文件来配置容器。
8.Unity支持开发者实现自定义容器扩展,例如:你可以实现方法来允许额外的对象构造和容器特征,例如缓存。
9.Unity允许架构师和开发者在现代化的程序中更简单的实现通用设计模式。