• Net6 DI源码分析Part2 Engine,ServiceProvider


    ServiceProvider

    ServiceProvider是对IServiceProvider实现,它有一个internal的访问修饰符描述的构造,并需要两个参数IServiceCollection & ServiceProviderOptions。所以可以通过 ServiceCollectionContainerBuilderExtensions提供的扩展方法和DefaultServiceProviderFactory工厂类创建实例。
    属性

    1. Func<Type, Func<ServiceProviderEngineScope, object>> _createServiceAccessor
    2. ServiceProviderEngine _engine;
    3. ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>> _realizedServices;
    4. CallSiteFactory CallSiteFactory { get; }
    5. ServiceProviderEngineScope Root { get; }
    6. CallSiteValidator _callSiteValidator;默认"创建服务存取器"的“工厂方法”

    方法

    1. void Dispose()
      很简单,做了一个事情,调用root的对应Dispose。清理容器构造出来的对象

    2. void OnCreate(ServiceCallSite callSite)
      此方法被用于每次通过CallSiteFactory创建出来的callsite进行验证然后使用_callSiteValidator去验证callsite

    3. object GetService(Type serviceType)
      很简单,调用同名方法,把root作为serviceProviderEngineScope传入。也就是你直接build出来的provider获取的服务均是root提供(废话)也经常被成为root provider(根容器的provider)。其 SingletonScoped类型的生命周期相同。

    4. internal GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
      很简单,根据type去realizedService如果有值拿对应的“创建服务存取器”否则创建一个默认的,也就是构造函数中初始化的 然后执行委托,把对应的serviceProviderEngineScope传入。
      存取器内部会有对应的engine。并把传入参数给engine。engine内部回把创建好的对象放入这个serviceProviderEngineScope内。

           Func<ServiceProviderEngineScope, object> realizedService = _realizedServices.GetOrAdd(serviceType, _createServiceAccessor);
           OnResolve(serviceType, serviceProviderEngineScope);
           var result = realizedService.Invoke(serviceProviderEngineScope);
           return result;
      
    5. Func<ServiceProviderEngineScope, object> CreateServiceAccessor(Type serviceType)
      作为默认的“创建服务存取器”工厂方法做了如下事情

      1. 通过CallSiteFactory获取对应的ServiceCallSite,并传入CallSiteChain。CallSiteChain防止循环依赖项
      2. 得到ServiceCallSite后调用OnCreate验证ServiceCallSite合规性。
      3. 如果是CallSiteResultCacheLocation.Root单例的,固定通过CallSiteRuntimeResolver(RuntimeServiceProviderEngine引擎的符类)产出物委托。算是对“单例”的优化。
      4. 其它生命周期通过_engine的RealizeService产出物委托。
       ServiceCallSite callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain());
       OnCreate(callSite);
       if (callSite.Cache.Location == CallSiteResultCacheLocation.Root)
       {
           object value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root);
           return scope => value;
       }
       return _engine.RealizeService(callSite);
      
    6. IServiceScope CreateScope();
      ServiceProvider作为所以ServiceProviderEngineScope的父节点
      return new ServiceProviderEngineScope(this, isRootScope: false);

      就算new 了一个新的ServiceProviderEngineScope其内部还是调用this指向的当前serviceProvider的CreateScope去创建对象.

    7. ServiceProviderEngine GetEngine()
      如何选择引擎,如果是NETFRAMEWORK ,NETSTANDARD2_0 并且支持DynamicCodeCompiled使用DynamicServiceProviderEngine引擎,否则使用RuntimeServiceProviderEngine

      1. DynamicServiceProviderEngine:DynamicServiceProviderEngine的特性是如果同一个类型同一时刻需要创建多次,那么它会使用ILEmitResolverBuilder/ExpressionResolverBuilder
      2. RuntimeServiceProviderEngineRuntimeServiceProviderEngine内部调用CallSiteRuntimeResolver创建对象 此class 是应用使用反射创建。
      ServiceProviderEngine engine;
      #if NETFRAMEWORK || NETSTANDARD2_0
           engine = new DynamicServiceProviderEngine(this);
       #else
           if (RuntimeFeature.IsDynamicCodeCompiled)
           {
               engine = new DynamicServiceProviderEngine(this);
           }
           else
           {
               // Don't try to compile Expressions/IL if they are going to get interpreted
               engine = RuntimeServiceProviderEngine.Instance;
           }
       #endif
       return engine;
      
    8. 构造方法

      1. 初始化Root
      2. GetEngine 构造服务引擎。
      3. 初始化默认的 _createServiceAccessorCreateServiceAccessor
      4. _realizedServices为每个服务缓存一个create Service Accessor(Func<ServiceProviderEngineScope, object>) 以Type作为key,默认为_createServiceAccessor 也就是CreateServiceAccessor
      5. 提供内部服务注册信息
      6. 根据ServiceProviderOptions Options 初始化验证
      Root = new ServiceProviderEngineScope(this, isRootScope: true);
      _engine = GetEngine();
      _createServiceAccessor = CreateServiceAccessor;
      _realizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>();
      CallSiteFactory = new CallSiteFactory(serviceDescriptors);
      CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
      CallSiteFactory.Add(typeof(IServiceScopeFactory), new ConstantCallSite(typeof(IServiceScopeFactory), Root));
      CallSiteFactory.Add(typeof(IServiceProviderIsService), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory));
      if (options.ValidateScopes)
      {
          _callSiteValidator = new CallSiteValidator();
      }
      if (options.ValidateOnBuild)
      {
          foreach (ServiceDescriptor serviceDescriptor in serviceDescriptors)
          {
                  ValidateService(serviceDescriptor);
          }
      }
      

    这里ServiceProivder的功能很明确单一职责,提供服务,创建Scope,提供引擎,即使ServiceProviderEngineScope也有同名方法,但最终都依赖于ServiceProivder。它们仅仅是包装了以下。

    ServiceProviderEngineScope

    它实现了IServiceScope IServiceProvider IServiceScopeFactory所以它可以获取服务,也可以创建Scope。
    属性。

    1. private List<object> _disposables;
    2. bool IsRootScope
    3. internal ServiceProvider RootProvider
    4. internal Dictionary<ServiceCacheKey, object> ResolvedServices { get; }
      方法。
    5. object GetService(Type serviceType)
    6. IServiceScope CreateScope() => RootProvider.CreateScope();
      CreateScope总是调用RootProvider的同名方法也就是说每一个新的ServiceProviderEngineScope它们的父节点都是同一个。也就是ServieProvider。ServiceProvider作为所以ServiceProviderEngineScope的父节点
    7. void Dispose()
    ServiceProviderEngine

    一抽象类唯一的方法为RealizeService 主要这里它仅仅返回的是一个委托,此委托的具体执行由ServiceProvider GetService执行
    public abstract Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite);

    DynamicServiceProviderEngine

    该类继承了CompiledServiceProviderEngine.并重写了父类的RealizeService,其内部还是通过CallSiteRuntimeResolver服务类去创建服务,但如果统一时刻某一类型被创建多次时,它会做出替换掉该类型的“创建服务存取器”为 base.RealizeService(callSite)也就是CompiledServiceProviderEngine.RealizeService
    可以说DynamicServiceProviderEngine职责是根据某一个Type的使用频率给出个对应类型的“创建服务存取器” ,不同的“创建服务存取器” 内使用了不同的引擎。

    CompiledServiceProviderEngine

    CompiledServiceProviderEngine是对ServiceProviderEngine的实现之一

    一个属性ResolverBuilder和一个RealizeService方法
    ResolverBuilder 它通过环境去构造出具体的属性ILEmitResolverBuilder/ExpressionResolverBuilder调用RealizeService方法是仅返回对应ResolverBuilder的产出物的委托。GetService

      internal abstract class CompiledServiceProviderEngine : ServiceProviderEngine
        {
    #if IL_EMIT
            public ILEmitResolverBuilder ResolverBuilder { get; }
    #else
            public ExpressionResolverBuilder ResolverBuilder { get; }
    #endif
     
            public CompiledServiceProviderEngine(ServiceProvider provider)
            {
                ResolverBuilder = new(provider);
            }
     
            public override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite) => ResolverBuilder.Build(callSite);
        }
    
    RuntimeServiceProviderEngine

    同样也是对抽象类ServiceProviderEngine的实现,重写抽象方法后,它内部直接返回CallSiteRuntimeResolver的Resolve方法的产出物的委托。

            public override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite)
            {
                return scope =>
                {
                    return CallSiteRuntimeResolver.Instance.Resolve(callSite, scope);
                };
            }
    

    >ServiceProviderEngine.Resolve总结

    Engine的Resolve方法返回的均是委托最终在serviceProivder的GetService中执行,得到实例对象也就是我们的最终交给使用者的服务。engine创建对象依赖的均是ServiceCallSite它是由CallSiteFactory根据Type创建的。

    IServiceScopeFactory

    唯一一个方法IServiceScope CreateScope();ServiceProviderEngineScope实现了此接口

    IServiceScope: IDisposable

    唯一一个属性IServiceProvider ServiceProvider { get; }ServiceProviderEngineScope实现了此接口

  • 相关阅读:
    SQL Server 2008 R2下载地址
    [转]sqlserver2014两台不同服务器上数据库同步
    笔记本(ThinkPad)怎样关闭触摸板
    10 Free Image Hosting Sites for Your Photos
    Photobucket不能用了怎么办?推荐10个在线图片储存服务!
    证书错误 导航已阻止 无法跳转 最终解决
    用websploit获取管理员后台地址
    10 Free Image Hosting Sites for Your Photos
    Css3动画属性总汇
    23个适合logo设计的常用英文字体
  • 原文地址:https://www.cnblogs.com/hts92/p/15800990.html
Copyright © 2020-2023  润新知