ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式,这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术。
先上一段代码,再基于代码解释DI以及DI的声明周期
public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance { public Operation() : this(Guid.NewGuid()) {
//构造操作ID以区分对象是创建情况。 } public Operation(Guid id) { OperationId = id; } public Guid OperationId { get; private set; } }
services.AddScoped<IMyDependency, MyDependency>(); services.AddTransient<IOperationTransient, Operation>(); services.AddScoped<IOperationScoped, Operation>(); services.AddSingleton<IOperationSingleton, Operation>(); services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty)); // OperationService depends on each of the other Operation types. services.AddTransient<OperationService, OperationService>(); //注意这是一个引用多个其他对象的服务类,请区分不同注入容器对象的生命周期
public class OperationService { public OperationService( IOperationTransient transientOperation, IOperationScoped scopedOperation, IOperationSingleton singletonOperation, IOperationSingletonInstance instanceOperation) { TransientOperation = transientOperation; ScopedOperation = scopedOperation; SingletonOperation = singletonOperation; SingletonInstanceOperation = instanceOperation; } public IOperationTransient TransientOperation { get; } public IOperationScoped ScopedOperation { get; } public IOperationSingleton SingletonOperation { get; } public IOperationSingletonInstance SingletonInstanceOperation { get; } }
页面control 构造函数注入
public IndexModel( IMyDependency myDependency, OperationService operationService, IOperationTransient transientOperation, IOperationScoped scopedOperation, IOperationSingleton singletonOperation, IOperationSingletonInstance singletonInstanceOperation) { _myDependency = myDependency; OperationService = operationService; TransientOperation = transientOperation; ScopedOperation = scopedOperation; SingletonOperation = singletonOperation; SingletonInstanceOperation = singletonInstanceOperation; } public OperationService OperationService { get; } //服务里面有依赖 TransientOperation SocpedOperation SingletonOperation public IOperationTransient TransientOperation { get; } public IOperationScoped ScopedOperation { get; } public IOperationSingleton SingletonOperation { get; } public IOperationSingletonInstance SingletonInstanceOperation { get; }
总结:从上述运行结果可以看出来 AddTransient 类似于一个工厂构造函数,每次构建不同的对象,相当于瞬时的生命周期。
AddScoped 首先Page页面对象与OperationService对象中引用的对象都是同一个,生命周期是基于应用域级别的。即一个Http请求到结束对象的生命周期也结束,可以看出刷新页面后这个对象会重新实例化。
AddSingleton 相当于一个静态类对象,刷新页面后始终发现这个ID没有变,不管是pageModel 与 OperationService 都是一直没有变。
因此我们可以根据需要来选择不同的注入,大多数情况应该是用AddScoped ,接下来来扒一下这个注入实现的原理。
依赖注入的原理先看看这个类型及函数
IServiceCollection AddScoped(this IServiceCollection services, Type serviceType, Type implementationType) //注入函数,服务类型,实现类型 总共两个参数。 public interface IServiceCollection : ICollection<ServiceDescriptor>, IEnumerable<ServiceDescriptor>, IEnumerable, IList<ServiceDescriptor> //服务注入容器接口,ServiceDescriptor这是一个关键 注入的信息都保存在这个描述类中。 //这里不展开了,有兴趣的可以去看一下源码netcore已经全面开源,这里吐槽一下以前半开源,追踪代码半天最后发现核心部分没有开源,看不到。 //实现原理大概是一个http请求映射到一个control类的时候,请求的handler会拿到这个构造函数的参数,然后根据参数类型去上面 IServiceCollection 会提供一个容器对象 //根据容器 ServiceDescriptor 查找到这个描述类,根据类型的信息去拿到对象或者延迟构建这个对象(如果是scoped singleton 类型会有一个缓存容器拿到这个引用),如果是 Transient类型 //则根据注入的参数构建一个新的对象并返回。大概原理就这样了 //那么怎么就实现了IOC呢,这里主要是因为我注入的时候在运行时,并且是根据配置参数注入的,所以就达到了运行时确定具体类型,达到控制反转。