ASP.NET Core6 lOC容器
控制反转(Inversion of Control, IoC)是一种软件设计模式,其目的是降低代码之间的耦合度。在C#中,可以使用依赖注入(Dependency Injection, DI)来实现控制反转。
一般系统分为 UI 层、BLL 层、DAL 层、IBLL 层 和 IDAL 层,IOC 实质是通过抽象 IBLL(接口、抽象类、普通父类)获取BLL层的实例,如果使用依赖注入,那么各层的关系如下:
内置容器 ServiceCollection 的应用
新建 Learn.NET6.Business.Interfaces 类库,新建 IMicrophone接口:
public interface IMicrophone
{
}
在 Learn.NET6.ExceptionService 层添加 Microphone 类:
public class Microphone : IMicrophone
{
public Microphone()
{
Console.WriteLine($"{this.GetType().Name}被构造。。");
}
}
新建 Learn.NET6.DemoTest 控制台应用程序,在 Program 类中:
需要注意的是 ServiceCollection 只支持构造函数注入。
{
//传统做法,创建一个实例
Microphone microphone = new Microphone();
IMicrophone microphone1 = new Microphone();
}
//内置容器:
{
//1.创建一个容器
//nuget 引入 Microsoft.Extensions.DependencyInjection
ServiceCollection serviceDescriptors = new ServiceCollection();
//2.注册抽象和具体普通类之间的关系
serviceDescriptors.AddTransient<IMicrophone, Microphone>();
//3. serviteDescriptors.builder
ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();
IMicrophone microphone = serviceProvider.GetService<IMicrophone>();
}
IOC容器-DI依赖注入
依赖注入
在创建对象的实例时,如果对象A,依赖于对象B,对象B依赖于对象C,那么在创建对象A的时候,
自动的把对象C创建出来交给对象B,再把对象B创建出来交给对象A,从而创建出对象A。
可以在全局跟一个ioc容器,配置抽象和具体普通之间的关系的时候,可以修改,这里修改了,获取实例就获取新的实例。
在 Learn.NET6.ExceptionService. 新建 AndroidPhone、ApplePhone、Headphone、Microphone、MicrophoneNew 和 Power 类,多个类且类之间互相引用:
public class AndroidPhone : IPhone
{
public IMicrophone Microphone { get; set; }
public IHeadphone Headphone { get; set; }
public IPower Power { get; set; }
public AndroidPhone()
{
Console.WriteLine("{0}构造函数", this.GetType().Name);
}
public void Call()
{
Console.WriteLine("{0}打电话", this.GetType().Name); ;
}
public void Init123456678890(IPower iPower)
{
Power = iPower;
}
public void Text()
{
Console.WriteLine("{0}发信息", this.GetType().Name); ;
}
public object QueryUser(object opara)
{
throw new NotImplementedException();
}
}
public class ApplePhone : IPhone
{
public IMicrophone Microphone { get; set; }
public IHeadphone Headphone { get; set; }
public IPower Power { get; set; }
public ApplePhone(IHeadphone iHeadphone)
{
this.Headphone = iHeadphone;
Console.WriteLine("{0}带参数构造函数", this.GetType().Name);
}
public virtual void Call()
{
Console.WriteLine("{0}打电话", this.GetType().Name); ;
}
public void Text()
{
Console.WriteLine("{0}发信息", this.GetType().Name); ;
}
public object QueryUser(object opara)
{
return new
{
Id = 123,
Name = "Richard",
DateTiem = DateTime.Now.ToString()
};
}
public void Init123456678890(IPower iPower)
{
this.Power = iPower;
}
}
public class Headphone : IHeadphone
{
public Headphone(IPower power)
{
Console.WriteLine($"{this.GetType().Name}被构造。。");
}
}
public class Microphone : IMicrophone
{
public Microphone()
{
Console.WriteLine($"{this.GetType().Name}被构造。。");
}
}
public class MicrophoneNew : IMicrophone
{
public MicrophoneNew()
{
Console.WriteLine($"{this.GetType().Name}被构造。。");
}
}
public class Power : IPower
{
private IMicrophone Microphone;
private IMicrophone Microphone2;
public Power(IMicrophone microphone)
{
Console.WriteLine($"{this.GetType().Name}被构造。。");
this.Microphone = microphone;
}
public Power(int microphone)
{
Console.WriteLine($"{this.GetType().Name}被构造。。");
}
public Power(IMicrophone microphone, IMicrophone microphone2)
{
Console.WriteLine($"{this.GetType().Name}被构造。。");
this.Microphone = microphone;
this.Microphone2 = microphone2;
}
}
在 Learn.NET6.Business.Interfaces 新建 IHeadphone、IMicrophone、IPhone 和 IPower:
public interface IHeadphone
{
}
public interface IMicrophone
{
}
public interface IPhone
{
void Call();
void Text();
void Init123456678890(IPower iPower);
IMicrophone Microphone { get; set; }
IHeadphone Headphone { get; set; }
IPower Power { get; set; }
object QueryUser(object opara);
}
public interface IPower
{
}
传统做法创建对象
{
// 传统做法创建对象
IMicrophone microphone = new Microphone();
IPower power = new Power(microphone);
IHeadphone headphone = new Headphone(power);
}
IOC容器支持依赖注入
{
//IOC容器支持依赖注入
ServiceCollection serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddTransient<IMicrophone, Microphone>();
serviceDescriptors.AddTransient<IPower, Power>();
serviceDescriptors.AddTransient<IHeadphone, Headphone>();
ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();
IHeadphone headphone = serviceProvider.GetService<IHeadphone>();
}
ServiceCollection 支持的生命周期
ServiceCollection--IOC容器本质就是来创建对象的;
那么在对象创建的时候,有些特殊的场景,需要创建出来的对象有的支持单例,有的在一些范围内支持单例,面对于这些诉求,ServiceCollection支持了三种生命周期来解决这个问题。
瞬时生命周期--Transient
//一、AddTransient:瞬时生命周期,每一次创建都是一个全新的实例
{
ServiceCollection serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddTransient<IMicrophone, Microphone>();
ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();
IMicrophone microphone1 = serviceProvider.GetService<IMicrophone>();
IMicrophone microphone2 = serviceProvider.GetService<IMicrophone>();
IMicrophone microphone3 = serviceProvider.GetService<IMicrophone>();
IMicrophone microphone4 = serviceProvider.GetService<IMicrophone>();
// 比较内存的引用地址,如果相同就表示同一个对象,结果是不相同
Console.WriteLine($"microphone1 比较 microphone2:{object.ReferenceEquals(microphone1, microphone2)}");
Console.WriteLine($"microphone1 比较 microphone3:{object.ReferenceEquals(microphone1, microphone3)}");
Console.WriteLine($"microphone2 比较 microphone4:{object.ReferenceEquals(microphone2, microphone4)}");
}
单例生命周期--Singleton
//一、AddSingleton:单例生命周期,每一次创建都是同一个实例
{
ServiceCollection serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddSingleton<IMicrophone, Microphone>();
ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();
IMicrophone microphone1 = serviceProvider.GetService<IMicrophone>();
IMicrophone microphone2 = serviceProvider.GetService<IMicrophone>();
IMicrophone microphone3 = serviceProvider.GetService<IMicrophone>();
IMicrophone microphone4 = serviceProvider.GetService<IMicrophone>();
// 比较内存的引用地址,如果相同就表示同一个对象,结果是相同
Console.WriteLine($"microphone1 比较 microphone2:{object.ReferenceEquals(microphone1, microphone2)}");
Console.WriteLine($"microphone1 比较 microphone3:{object.ReferenceEquals(microphone1, microphone3)}");
Console.WriteLine($"microphone2 比较 microphone4:{object.ReferenceEquals(microphone2, microphone4)}");
}
作用域生命周期--Scoped
//一、AddScoped:作用域生命周期,同一个serviceProvider获取到的是同一个实例
{
ServiceCollection serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddScoped<IMicrophone, Microphone>();
ServiceProvider serviceProvider1 = serviceDescriptors.BuildServiceProvider();
IMicrophone microphone1 = serviceProvider1.GetService<IMicrophone>();
IMicrophone microphone2 = serviceProvider1.GetService<IMicrophone>();
ServiceProvider serviceProvider2 = serviceDescriptors.BuildServiceProvider();
IMicrophone microphone3 = serviceProvider2.GetService<IMicrophone>();
IMicrophone microphone4 = serviceProvider2.GetService<IMicrophone>();
// 比较内存的引用地址
Console.WriteLine($"microphone1 比较 microphone2:{object.ReferenceEquals(microphone1, microphone2)}"); //True
Console.WriteLine($"microphone3 比较 microphone4:{object.ReferenceEquals(microphone3, microphone4)}"); //True
Console.WriteLine($"microphone1 比较 microphone3:{object.ReferenceEquals(microphone1, microphone3)}"); //False
Console.WriteLine($"microphone1 比较 microphone1:{object.ReferenceEquals(microphone1, microphone4)}"); //False
}