DependencyInjection源码解读之ServiceProvider
var services = new ServiceCollection(); var _serviceProvider = services.BuildServiceProvider(); serviceScope = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope() var internalServiceProvider = serviceScope.ServiceProvider;
上面几行代码内部发生了什么?
要弄清这个过程,我们先得了解一下ServiceProvider创建过程.
ServiceProvider 有两个构造方法,一个用来创建Root ServiceProvider ,和个用来创建 Not Root ServiceProvider。
为了方便称呼,我们把它们称为 RootServiceProvider和 InternalServiceProvider
构造方法一,用来创建一个rootServiceProvider,Root属性指向自己。
internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options) { Root = this; if (options.ValidateScopes) { _callSiteValidator = new CallSiteValidator(); } _table = new ServiceTable(serviceDescriptors); _table.Add(typeof(IServiceProvider), new ServiceProviderService()); _table.Add(typeof(IServiceScopeFactory), new ServiceScopeService()); _table.Add(typeof(IEnumerable<>), new OpenIEnumerableService(_table)); }
构造方法二,用来创建一个InternalServiceProvider,Root属性指向传入的ServiceProvider(居然可以单性繁殖)。
internal ServiceProvider(ServiceProvider parent) { Root = parent.Root; _table = parent._table; _callSiteValidator = parent._callSiteValidator; }
注意:RootServiceProvider 和 InternalServiceProvider 并没有什么本质上的不同,但还是有两点区别:
1.RootServiceProvider 的 Root 属性指向的是自己,而 InternalServiceProvider 指向的是 RootServiceProvider
2.RootServiceProvider 创建时会创建一个新的ServiceTable,并注册三个默认的依赖服务。
_table = new ServiceTable(serviceDescriptors); //注入默认的依赖注入,这样才能在使用 _serviceProvider.GetRequiredService<IServiceScopeFactory>() 或在创建对象时为构造方法中的IServiceProvider 注入实例。 _table.Add(typeof(IServiceProvider), new ServiceProviderService()); _table.Add(typeof(IServiceScopeFactory), new ServiceScopeService()); _table.Add(typeof(IEnumerable<>), new OpenIEnumerableService(_table));
回到最上面的几行代码,跟据参数可以看到。
BuildServiceProvider() 创建的是 RootServiceProvider, serviceScope.ServiceProvider 创建的是 InternalServiceProvider
具体过程为:
// BuildServiceProvider() 是扩展方法,有三个重载 //最终实现方法定义:this IServiceCollection services, ServiceProviderOptions options //其中services是当前扩展的IServiceCollection,options是一些可选扩展选项 BuildServiceProvider() == new ServiceProvider(services, options); _serviceProvider.GetRequiredService<IServiceScopeFactory>(); //这一句获取一个ServiceScopeFactory实例,IServiceScopeFactory我们上面说过了,创建RootServiceProvider时内部注册的。 // CreateScope() // CreateScope()是在IServiceScopeFactory接口内定义,ServiceScopeFactory类的实现为: //return new ServiceScope(new ServiceProvider(_provider)); //其中_provider参数类型为ServiceProvider,是ServiceScopeFactory类的一个字段,其值来自构造方法注入 CreateScope() == new ServiceScope(new ServiceProvider(_provider));
需要注意的是,它们所在方法接收的参数 IServiceCollection 还是 ServiceProvider
如果接收的是IServiceCollection,是可以直接转化为 IEnumerable<ServiceDescriptor>的。因为IServiceCollection 是一个继承自 IList<ServiceDescriptor>的空接口。
所以BuildServiceProvider()所在方法接收的参数 IServiceCollection services 直接转化为构造方法一所需要的 IEnumerable<ServiceDescriptor> serviceDescriptors
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?