细聊.Net Core中IServiceScope的工作方式( 五 )

上面我们看到的RealizeService()方法返回的是一个委托,而调用这个委托的地方则是上面源码中看到的realizedService.Invoke(serviceProviderEngineScope),核心操作在CallSiteRuntimeResolver.Instance.Resolve()方法 , Resolve方法的核心逻辑在VisitCallSite()方法,看一下它的实现方式[点击查看源码]
protected virtual TResult VisitCallSite(ServiceCallSite callSite, TArgument argument){    if (!_stackGuard.TryEnterOnCurrentStack())    {        return _stackGuard.RunOnEmptyStack((c, a) => VisitCallSite(c, a), callSite, argument);    }    switch (callSite.Cache.Location)    {        //ServiceLifetime.Singleton单例情况        case CallSiteResultCacheLocation.Root:            return VisitRootCache(callSite, argument);        //ServiceLifetime.Scoped作用域情况,也就是咱们关注的情况        case CallSiteResultCacheLocation.Scope:            return VisitScopeCache(callSite, argument);        //ServiceLifetime.Transient瞬时情况        case CallSiteResultCacheLocation.Dispose:            return VisitDisposeCache(callSite, argument);        case CallSiteResultCacheLocation.None:            return VisitNoCache(callSite, argument);        default:            throw new ArgumentOutOfRangeException();    }}因为我们关注的是CallSiteResultCacheLocation.Scope这种情况所以我们重点关注的是VisitScopeCache()这段方法逻辑,CallSiteRuntimeResolver的VisitCache()方法[点击查看源码]
protected override object VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context){    //咱们关注的是Scope的情况 , 所以重点在VisitCache方法    return context.Scope.IsRootScope ?        VisitRootCache(callSite, context) :        VisitCache(callSite, context, context.Scope, RuntimeResolverLock.Scope);}//这里的serviceProviderEngine参数就是我们传递进来的ServiceProviderEngineScope实例private object VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType){    bool lockTaken = false;    //获取ServiceProviderEngineScope的Sync属性    object sync = serviceProviderEngine.Sync;    //获取ServiceProviderEngineScope的ResolvedServices属性    Dictionary<ServiceCacheKey, object> resolvedServices = serviceProviderEngine.ResolvedServices;    //加锁    if ((context.AcquiredLocks & lockType) == 0)    {        Monitor.Enter(sync, ref lockTaken);    }    try    {        //判断ServiceProviderEngineScope的ResolvedServices的属性里是否包含该类型实例        //当前作用域内只有一个实例,所以缓存起来        if (resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved))        {            return resolved;        }        //当前Scope没创建过实例的话则创建        resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext        {            Scope = serviceProviderEngine,            AcquiredLocks = context.AcquiredLocks | lockType        });        //判断当前类型实例是否是IDispose想实例        serviceProviderEngine.CaptureDisposable(resolved);        //给ServiceProviderEngineScope的ResolvedServices的属性添加缓存实例        resolvedServices.Add(callSite.Cache.Key, resolved);        return resolved;    }    finally    {        if (lockTaken)        {            Monitor.Exit(sync);        }    }}protected virtual TResult VisitCallSiteMain(ServiceCallSite callSite, TArgument argument){    //比如我们上面的services.AddScoped<Person>(provider => new() { Id = 1, Name = "yi念之间", Sex = "Man" })    //对应的Kind则是CallSiteKind.Factory    switch (callSite.Kind)    {        case CallSiteKind.Factory:            //调用了VisitFactory方法            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()));    }}protected override object VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context){  //调用我们注册的services.AddScoped<Person>(provider => new() { Id = 1, Name = "yi念之间", Sex = "Man" })  //FactoryCallSite的Factory即是provider => new() { Id = 1, Name = "yi念之间", Sex = "Man" }  //context.Scope则是我们通过CreateScope创建的实例  //返回的结果就是调用当前委托得到的实例即我们实例中的Person实例  return factoryCallSite.Factory(context.Scope);}

推荐阅读