• Net6 DI源码分析Part3 CallSiteRuntimeResolver,CallSiteVisitor


    CallSiteRuntimeResolver

    CallSiteRuntimeResolver是实现了CallSiteVisitor之一。
    提供的方法主要分三个部分

    1. 自有成员方法

      1. Resolve提供服务
      2. VisitCache
      3. 私有构造函数
    2. 重写父类方法

      1. VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
        调用父类VisitCallSiteMain ,并把创建出来的服务添加到context.Scope.CaptureDisposable

        return context.Scope.CaptureDisposable(VisitCallSiteMain(transientCallSite, context));
        
      2. object VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)

        1. 先找对应callSite.Value是否有值如果有直接返回
        2. 如果没有直接调用 VisitCallSiteMain创建服务并把对象rootServiceProviderEngine内。
        3. 创建的服务放入callSite.Value。
            if (callSite.Value is object value) 
            {
                return value;
            }
        
        var lockType = RuntimeResolverLock.Root;
        ServiceProviderEngineScope serviceProviderEngine = context.Scope.RootProvider.Root;
        if (callSite.Value is object resolved)
        {
            return resolved;
        }
        resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
        {
            Scope = serviceProviderEngine,
            AcquiredLocks = context.AcquiredLocks | lockType
        });
        serviceProviderEngine.CaptureDisposable(resolved);
        callSite.Value = resolved;
        return resolved;
        
      3. VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)

        1. 先去serviceProviderEngine.resolvedServices拿,有的话直接返回如果没拿到执行步骤2去创建。serviceProviderEngine.resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved)
        2. VisitCallSiteMain创建对象
        3. 把创建后的对象加入对应Scope的 disposable列表
        4. 把创建后的对象加入对应Scope的 resolvedServices列表
            if (resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved))
            {
                return resolved;
            }
            resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
            {
                Scope = serviceProviderEngine,
                AcquiredLocks = context.AcquiredLocks | lockType
            });
            serviceProviderEngine.CaptureDisposable(resolved);
            resolvedServices.Add(callSite.Cache.Key, resolved);
            return resolved;
        
    3. 实现父类抽象方法

      1. VisitConstructor
        1. 给构造方法提供参数(如果有参数递归调用VisitCallSite创建参数对象)
        2. 直接调用ServiceCallSite的ConstructorInfo反射创建对象。
           object[] parameterValues;
            if (constructorCallSite.ParameterCallSites.Length == 0)
            {
                parameterValues = Array.Empty<object>();
            }
            else
            {
                parameterValues = new object[constructorCallSite.ParameterCallSites.Length];
                for (int index = 0; index < parameterValues.Length; index++)
                {
                    parameterValues[index] = VisitCallSite(constructorCallSite.ParameterCallSites[index], context);
                }
            }
        
            return constructorCallSite.ConstructorInfo.Invoke(BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameterValues, culture: null);
        
      2. override object VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context)
        直接返回CallSite对象的DefaultValue
        return constantCallSite.DefaultValue;
      3. VisitServiceProvider
        return context.Scope;
      4. override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
        根据ServiceCallSites直接循环调用VisitCallSite创建实例,然后根据实例创建集合返回
          var array = Array.CreateInstance(
          enumerableCallSite.ItemType,
          enumerableCallSite.ServiceCallSites.Length);
          for (int index = 0; index < enumerableCallSite.ServiceCallSites.Length; index++)
          {
              object value = VisitCallSite(enumerableCallSite.ServiceCallSites[index], context);
              array.SetValue(value, index);
          }
          return array;
        
      5. VisitFactory
        return factoryCallSite.Factory(context.Scope);

    体力活都给CallSiteFactory

    CallSiteVisitor
    1. 方法
      1. VisitCallSite(ServiceCallSite callSite, TArgument argument)

        1. 保证Stack安全
        2. 根据callSite的Cache.Location去调用不同策略的Cache方法。
        switch (callSite.Cache.Location)
             {
                 case CallSiteResultCacheLocation.Root:
                     return VisitRootCache(callSite, argument);
                 case CallSiteResultCacheLocation.Scope:
                     return VisitScopeCache(callSite, argument);
                 case CallSiteResultCacheLocation.Dispose:
                     return VisitDisposeCache(callSite, argument);
                 case CallSiteResultCacheLocation.None:
                     return VisitNoCache(callSite, argument);
                 default:
                     throw new ArgumentOutOfRangeException();
         }
        
      2. VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)

        1. 根据不同CallSiteKind去调用不同策略的创建服务方法。
           switch (callSite.Kind)
            {
                case CallSiteKind.Factory:
                    return VisitFactory((FactoryCallSite)callSite, argument);
                case  CallSiteKind.IEnumerable:
                    return VisitIEnumerable((IEnumerableCallSite)callSite, argument);
                case CallSiteKind.Constructor:
                    return VisitConstructor((ConstructorCallSite)callSite, argument);
                case CallSiteKind.Constant:
                    return VisitConstant((ConstantCallSite)callSite, argument);
                case CallSiteKind.ServiceProvider:
                    return VisitServiceProvider((ServiceProviderCallSite)callSite, argument);
                default:
                    throw new NotSupportedException(SR.Format(SR.CallSiteTypeNotSupported, callSite.GetType()));
            }
          
    2. 虚方法
      1. TResult VisitNoCache(ServiceCallSite callSite, TArgument argument) => VisitCallSiteMain(callSite, argument);
      2. TResult VisitDisposeCache(ServiceCallSite callSite, TArgument argument) -> isitCallSiteMain(callSite, argument);
      3. TResult VisitRootCache(ServiceCallSite callSite, TArgument argument) -> VisitCallSiteMain(callSite, argument);
      4. TResult VisitScopeCache(ServiceCallSite callSite, TArgument argument) => VisitCallSiteMain(callSite, argument);

      根据生命周期策略由子类实现对应存储机制。

    3. 抽象方法
      1. TResult VisitConstructor(ConstructorCallSite constructorCallSite, TArgument argument);
      2. TResult VisitConstant(ConstantCallSite constantCallSite, TArgument argument);
      3. TResult VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, TArgument argument);
      4. TResult VisitIEnumerable(IEnumerableCallSite enumerableCallSite, TArgument argument);
      5. TResult VisitFactory(FactoryCallSite factoryCallSite, TArgument argument);

      根据服务注册时的创建机制策略由子类实现对应的创建对象机制。

    CallSiteVisitor负责这活怎么干!。CallSiteRuntimeResolver负责干活

    1. 调用 VisitCallSite在内部区分出scope并调用具体实现方法缓存方法 (CallSiteResultCacheLocation),
      -> VisitCache方法
      -> 但是在缓存前得先得到被缓存的对象,这时通过调用(VisitCallSiteMain)创建对象
      -> VisitCallSiteMain根据提供的callsite类型去调用实现的抽象方法创建对应对象
      -> 根据cache对应的方法缓存步骤1.1的结果。
    2. return cahce的结果。
    整体的获取对象流程大约如下

    CallSiteRuntimeResolver.Resolve -> CallSiteVisitor->VisitCallSite callSite.Cache.Location VisitRootCache/VisitScopeCache/ VisitDisposeCache/ VisitNoCache -> CallSiteRuntimeResolver.VisitCache/ VisitRootCache -> VisitRootCache -> CallSiteVisitor.VisitCallSiteMain 根据callSite.Kind CallSiteRuntimeResolver.VisitFactory(abstract TResult VisitFactory)递归调用 VisitCallSite

  • 相关阅读:
    day15 web框架和Django基础
    activiti5.22 获得mybatis sessionFactory
    activiti 视图
    activiti 任意退
    spring cloud &&spring boot
    JPA 一对多关联
    webstorm 快捷键
    web storm 破解
    Excel通用导出
    activiti 小计
  • 原文地址:https://www.cnblogs.com/hts92/p/15812761.html
Copyright © 2020-2023  润新知