上面我们看到的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);}
推荐阅读
- asp.net core web 解决方案多项目模板制作打包总结
- ubuntu-22.04 树莓派Zero 2 W通过.NET6和libusb操作USB读写
- 上 学习ASP.NET Core Blazor编程系列六——新增图书
- Azure DevOps Pipelines部署.Net Core 应用到Kubernetes
- C语言小白刷题
- 记一次 .NET 某企业OA后端服务 卡死分析
- .NET 采用 SkiaSharp 生成二维码和图形验证码及图片进行指定区域截取方法实现
- .Net CLR异常简析
- 记一次 .NET 某电子病历 CPU 爆高分析
- .NET 7 RC 2 发布,倒计时一个月发布正式版