首页后端开发ASP.NETasp.net core 依赖注入实现全过程粗略剖析(2)

asp.net core 依赖注入实现全过程粗略剖析(2)

时间2023-12-03 03:07:02发布访客分类ASP.NET浏览1253
导读:接着 上篇 目前也算是交代清楚了相关的类。那么框架具体是如何来实例化的呢?整个的流程是怎么样的。我们参考源码中的Test文件夹来看看:var collection = new ServiceCollection( ; collection....

接着 上篇 目前也算是交代清楚了相关的类。那么框架具体是如何来实例化的呢?整个的流程是怎么样的。

我们参考源码中的Test文件夹来看看:

var collection = new ServiceCollection();
    
collection.AddTransientDependOnNonexistentService>
    ();
    
var provider = CreateServiceProvider(collection);
    

protected override IServiceProvider CreateServiceProvider(IServiceCollection collection) =>
     collection.BuildServiceProvider();


public static ServiceProvider BuildServiceProvider(this IServiceCollection services)
{
    
    return BuildServiceProvider(services, ServiceProviderOptions.Default);

}


public class ServiceProviderOptions
{
    
    // Avoid allocating objects in the default case
    internal static readonly ServiceProviderOptions Default = new ServiceProviderOptions();
    

    /// summary>
    
    /// c>
    true/c>
     to perform check verifying that scoped services never gets resolved from root provider;
     otherwise c>
    false/c>
    .
    /// /summary>

    public bool ValidateScopes {
     get;
     set;
 }


    internal ServiceProviderMode Mode {
     get;
     set;
 }
     = ServiceProviderMode.Dynamic;

}


internal enum ServiceProviderMode
{

    Dynamic,
    Runtime,
    Expressions,
    ILEmit
}


public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
{

    if (services == null)
    {
    
        throw new ArgumentNullException(nameof(services));

    }


    if (options == null)
    {
    
        throw new ArgumentNullException(nameof(options));

    }
    

    return new ServiceProvider(services, options);

}
    

internal ServiceProvider(IEnumerableServiceDescriptor>
 serviceDescriptors, ServiceProviderOptions options)
{
    
    IServiceProviderEngineCallback callback = null;

    if (options.ValidateScopes)
    {
    
        callback = this;
    
        _callSiteValidator = new CallSiteValidator();

    }

    switch (options.Mode)
    {
    
        case ServiceProviderMode.Dynamic:
            _engine = new DynamicServiceProviderEngine(serviceDescriptors, callback);
    
            break;
    
        case ServiceProviderMode.Runtime:
            _engine = new RuntimeServiceProviderEngine(serviceDescriptors, callback);
    
            break;
    
#if IL_EMIT
        case ServiceProviderMode.ILEmit:
            _engine = new ILEmitServiceProviderEngine(serviceDescriptors, callback);
    
            break;
    
#endif
        case ServiceProviderMode.Expressions:
            _engine = new ExpressionsServiceProviderEngine(serviceDescriptors, callback);
    
            break;
    
        default:
            throw new NotSupportedException(nameof(options.Mode));

    }

}
    

如上所示,就是注入服务,实例化服务的整个过程了。我们主要是根据IServiceCollection的扩展方法BuilServiceProvider调用ServiceProvider类,进而实例化相关服务。

除去这种方式实现ServiceProvider外,默认asp.net core框架中还有一个DefaultServiceProviderFactory。不过这个工厂类最后也是调用IServiceCollection接口的拓展方法--BuildServiceProvider来创建ServiceProvider类。

总结: IServiceCollection接口的拓展方法Addxxx 收集需要注入的服务,服务实现类型,服务的生命周期。这些就是在ServiceDescriptor中获取到的,也是该类的属性对象。这个也是IServiceCollection继承自IListServiceDescriptor> 的解释所在。随后再获取ServiceProviderOptions枚举对象,选择实现实例化的类型,比如反射等。最后就是调用BuildServiceProvider来生成ServiceProvider了。ServiceProvider根据选择之前的选择及配置,实例化服务。

除去最后使用反射等来实例化服务之外,可以看出asp.net core的DI框架的设计思路是这样的: 将需要服务对象抽象化,首先,一个服务要进行DI,需要知道的是服务对象,实例对象,服务生命周期。将这三点抽象成一个ServiceDescriptor服务描述符对象。 由于需要DI的服务有很多,因此抽象出来一个容器来存储每个服务的三大对象(我们只叙述重要,常用的三个对象),也就是我们上面抽象出来的描述符对象。这个容器我们使用ServiceCollection来表示,它继承自IServiceCollection,而IServiceCollection其实就是IListServiceDescriptor> 的集合,代表着众多的注入服务。服务的实例化我们抽象出来一个类:ServiceProvider,它实现一个接口,该接口只有一个方法GetService,表示获取指定服务的实例。 而我们将服务的实例化放在了该类的构造函数中,同时给它传入一个ServiceDescriptor集合对象,这个对象就包裹着需要注入服务的详细信息。随后使用指定的方式(在这里其实又抽象出来了一个配置类来指定实例化服务的方式)来实例化服务。

因此,ServiceCollection提供增删功能,这是对于ServiceDescriptor来存储的,ServiceDescriptor则是需要注入的服务的描述信息的抽象。ServiceProvider则是根据传入的配置类以及服务描述信息集合来实例化指定服务。

整个的设计思路其实就是一个抽象化的过程。这在设计中很有借鉴价值。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: asp.net core 依赖注入实现全过程粗略剖析(2)
本文地址: https://pptw.com/jishu/565630.html
5. abp集成asp.net core asp.net core 依赖注入实现全过程粗略剖析(1)

游客 回复需填写必要信息