您现在的位置是:首页 >学无止境 >.Net6.0系列-8 依赖注入(一)网站首页学无止境
.Net6.0系列-8 依赖注入(一)
依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式,依赖注入简化模块的组装过程,降低模块之间的耦合度.
DI的几个概念:
服务(Service):和框架请求之后返回的一个对象,可以是一个数据库链接,也可以是一个文件处理的方法,或者是数据处理的一个过程方法
注册服务:将上面向框架要的这个服务先注册,才能向框架请求
服务容器:负责管理注册的服务
查询服务:创建对象及关联对象
对象生命周期有三种:
(1)Transient(瞬态):获取服务对象每次获取都是一个新的对象
(2)Scoped(范围):在特定范围内再次获取为同一个对象
(3)Singleton(单例):就这一个对象,每次获取都是他
如果一个类实现了IDisposable接口,则离开作用域后容器会自动调用对象的Dispose方法,参考Using
生命周期的选择:如果类无状态,建议选为Singleton,如果类中有状态且有Scope控制就使用Scoped
.Net中使用DI
1.根据类型来获取和注册服务:
可以分别指定服务类型和实现类型.这两者可能相同,也可能不同.服务类型可以是类,也可以是接口,一般面向接口编程更灵活
2…Net控制反转组件取名为DependencyInjection,但是包含ServiceLocator的功能
3.ServiceCollection用来构造容器对象IServiceProvider,调用ServiceCollection的BuliderServiceProvider()创建ServiceProvider,可以用来获取BuliderServiceProvider()之前ServiceCollection中的对象
安装包需求:
Install-Package Microsoft.Extensions.DependencyInjection
using Microsoft.Extensions.DependencyInjection
GetService是根据注册对象来返回的
GetRequiredService:没有服务就抛出异常,因为required是必须有服务,当有多个服务的时候获取的是最后一个服务
GetServices:获取注册的所有的服务,
public interface ITestService
{
public string Name{get;set;}
public void SayHi();
}
public class TestServiceImpl:ItestService
{
public string Name{get;set;}
public void SayHi()
{
Console.WriteLine($"Hi,I'm{Name}");
}
}
public class TestServiceImpl2:ItestService
{
public string Name{get;set;}
public void SayHi()
{
Console.WriteLine($"你好,我是{Name}");
}
}
static void Main(string[] args)
{
#region 直接注册实现类,和接口没有关系,将实现类注册到服务容器中,然后通过实现类获取服务
ServiceCollection services=new ServiceCollection();
services.AddTransient<TestServiceImpl>();
//下面是两种申请服务的方法,一种是sp.GetServices/一种是sp.CreateScope()
using(ServiceProvider sp= services.BulidServiceProvider())
{
TestServiceImpl tsi=sp.GetService<TestServiceImpl>();
t.Name="cdc";
t.SayHi();
using(IServiceScope scope1=sp.CreateScope())
{
TestServiceImpl t=scope1.ServiceProvider.GetService<TestServiceImpl>();
}
}
#endregion
}
static void Main(string[] args)
{
ServiceCollection services=new ServiceCollection();
//注册类型是接口,实现类型是方法
services.AddScoped<ITestService,TestServiceImpl>();
//这种写法是为了传参数
services.AddSingleton<ITestService,new TestServiceImpl()>
using(ServiceProvider sp=services.BulidServiceProvider())
{
ITestService ts1=sp.GetService<ITestService>();
//ITestService ts1=(ITestService)sp.GetService(typeof(ITestService));
ts1.Name="cdc";
ts1.SayHi();
}
}
DI会传染的简单范例
namespace DIGOALL
{
class Progrom
{
static void Main(string[] args)
{
ServiceClolection services=new ServiceCollection();
services.AddScoped<Controller>();
services.AddScoped<ILog,LogImpl>();
services.AddScoped<IStorage,StorageImpl>();
services.AddScoped<IConfig,ConfigImpl>();
using(var sp= services.BulidServiceProvider())
{
var c=sp.GetRequiredService<Controller>();
c.Test();
}
Console.ReadKey();
}
}
class Controller
{
private readonly ILog log;
private readonly IStorage storage;
public Controller(ILog log,IStorage storage)
{
this.log=log;
this.storage=storage;
}
public void Test()
{
this.log.Log("开始上传");
this.storage.Save("写入的东西","1.txt");
this.log.Log("上传完毕");
}
}
#region 日志类
interface ILog
{
public void Log(string msg);
}
class LogImpl:ILog
{
public void Log(string msg)
{
Console.WriteLine($"日志:{msg}");
}
}
#endregion
#region
interface IConfig
{
public string GetValue(string name);
}
class ConfigImpl:IConfig
{
public void GetValue(string name)
{
return "hello";
}
}
#endregion
#region 云存储
interface IStorage
{
public void Save(string content,string name);
}
class StorageImpl:IStorage
{
**关键点:获取配置服务,构造函数中赋值给成员变量**
private readonly IConfig config;
public StorageImpl(IConfig config)
{
this.config=config;
}
public void Save(string content,string name)
{
string server=config.GetValue("server");
Console.WriteLine($"向服务器{server}的文件名为{name}上传{content}");
}
}
#endregion
}