下大致看一下,因为接下来会涉及到ServiceProviderEngineScope
这个类 。到目前为止涉及到了两个比较重要的类ServiceProvider
和ServiceProviderEngineScope
, 它们都是实现了IServiceProvider
接口 。看起来有点乱的样子,不过我们可以姑且这么理解 。ServiceProvider是IServiceProvider的直系实现类 , 作为IServiceProvider根容器的实现 。ServiceProviderEngineScope是用于,通过IServiceProvider创建作用域时表现出来的实例,也就是非根容器的实例 。
探究获取方法关于上面的介绍,我们其实探究了一点serviceProvider.CreateScope()
,接下来我们就需要看一下关于获取的相关操作,也就是GetService
方法相关,它的使用形式是serviceScope.ServiceProvider.GetService<T>()
。上面我们提到过ServiceProviderEngineScope
的ServiceProvider
属性实例则是当前ServiceProviderEngineScope的实例,所以我们直接去看ServiceProviderEngineScope
的GetService
方法[点击查看源码]
internal sealed class ServiceProviderEngineScope : IServiceScope, IServiceProvider, IAsyncDisposable, IServiceScopeFactory{ private bool _disposed; internal ServiceProvider RootProvider { get; } public object GetService(Type serviceType) { //判断当前实例是否释放 if (_disposed) { //如果已经释放则直接抛出异常 ThrowHelper.ThrowObjectDisposedException(); } return RootProvider.GetService(serviceType, this); }}看着挺乱的 , 各种跳转各种调用 。不过本质只设计到两个类ServiceProvider
和ServiceProviderEngineScope
,先说明一下,省的大家看着整蒙圈了 。通过最后一句代码,我们又能得到两个比较重要的信息 。
- ServiceProviderEngineScope的GetService方法,本质是在调用RootProvider的GetService方法 。通过前面咱们的源码分析可以知道
RootProvider
属性的值是ServiceProvider
实例也就是代表的根容器 。
- 调用RootProvider的GetService方法的时候传递了当前ServiceProviderEngineScope实例 。
public sealed class ServiceProvider : IServiceProvider, IDisposable, IAsyncDisposable{ private bool _disposed; private ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>> _realizedServices; private readonly Func<Type, Func<ServiceProviderEngineScope, object>> _createServiceAccessor; internal ServiceProviderEngine _engine; internal ServiceProvider() { _createServiceAccessor = CreateServiceAccessor; _realizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>(); } internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) { //判断当前实例是否释放 if (_disposed) { ThrowHelper.ThrowObjectDisposedException(); } //缓存获取服务实例委托的字典,值为要获取实例的类型,值是创建实例的委托 //_createServiceAccessor本质是CreateServiceAccessor方法委托 Func<ServiceProviderEngineScope, object> realizedService = _realizedServices.GetOrAdd(serviceType, _createServiceAccessor); OnResolve(serviceType, serviceProviderEngineScope); DependencyInjectionEventSource.Log.ServiceResolved(this, serviceType); //执行realizedService委托,传递的是ServiceProviderEngineScope实例 var result = realizedService.Invoke(serviceProviderEngineScope); System.Diagnostics.Debug.Assert(result is null || CallSiteFactory.IsService(serviceType)); return result; } private Func<ServiceProviderEngineScope, object> CreateServiceAccessor(Type serviceType) { //获取ServiceCallSite,其实就是获取要解析对象的实例相关信息 ServiceCallSite callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain()); if (callSite != null) { DependencyInjectionEventSource.Log.CallSiteBuilt(this, serviceType, callSite); OnCreate(callSite); //咱们当前讨论的是Scope周期对象的问题 , 这个方法描述的是生命周期为ServiceLifetime.Singleton的情况,可以跳过这个逻辑 //如果是单例情况,则直接在根容器中直接去操作对象实例,和当前的ServiceProviderEngineScope无关 if (callSite.Cache.Location == CallSiteResultCacheLocation.Root) { object value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root); return scope => value; } //解析ServiceCallSite里的信息 return _engine.RealizeService(callSite); } return _ => null; }}
推荐阅读
- 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 发布,倒计时一个月发布正式版