.net core 3.1 依赖注入的内部结构介绍 电脑版发表于:2021/2/23 16:37 ![.netcore](https://img.tnblog.net/arcimg/hb/c857299a86d84ee7b26d181a31e58234.jpg ".netcore") >#.net core 3.1 依赖注入的内部结构介绍 [TOC] 安装环境包 ------------ Microsoft.Extensions.DependencyInjection.Abstractions Microsoft.Extensions.DependencyInjection ServiceDescriptor服务注册类 ------------ tn>它是一个针对服务注册项的描述类,`IServiceProvider`正式利用该对象提供的描述信息才得以提供我们所需要的服务实例,内部包含服务类型、生命周期与构造方法等信息,具体如下所示: ![](https://img.tnblog.net/arcimg/hb/eaf495485c6b4e2d8c681b98adffc73c.png) | 属性 | 描述 | | ------------ | ------------ | | 前三个属性 | 表示具体实现的方式 | | `ServiceLifetime` | 生命周期,有`Singleton`(单例),`Scoped`(局部)与`Transient`(瞬时) | | `ServiceType` | 表示需要注册的接口类型 | IServiceCollection服务注册集合类 ------------ tn>`IServiceCollection`是一个存放服务注册信息(`ServiceDescriptor`)的集合。考虑到高频调用,它有许多扩展的方法。它与服务注册的描述类如下图所示: ![](https://img.tnblog.net/arcimg/hb/be4f20e834594bf9bbb84cbd829d41a6.png) tn>关于它们的扩展方法请参考文章:https://www.tnblog.net/hb/article/details/3627 IServiceProvider获取服务实例接口 ------------ tn>`IServiceCollection`集合最终被用来创建作为依赖注入容器`IServiceProvider`对象。当需要消费某个服务实例的时候我们,只需要指定服务类型调用`IServiceProvider`接口的`GetService`方法,该方法能够根据服务注册信息提供对应的服务实例。`IServiceProvider`可以通过`IServiceCollection`服务`BuildServiceProvider`方法创建出来。由于需要解决当一个服务注册时,同时有局部注册和单例注册的时候,此时单例注册的生命周期==局部的生命周期这会相当的不合理,所以需要服务的验证,在`BuildServiceProvider`中的第二个参数就是关于服务验证的配置。 ![](https://img.tnblog.net/arcimg/hb/e5c140b44a8b4e16acf7bd3c6fe45f88.png) ![](https://img.tnblog.net/arcimg/hb/9db40934b77344d3be6270dbd919e5ce.png) IServiceScopeFactory创建局部容器接口工厂 ------------ ![](https://img.tnblog.net/arcimg/hb/a552c762491c443089b9c0292c3f9417.png) tn>通过该接口可以对局部容器进行实例,里面只有一个`CreateScope`方法可以创建局部容器(`IServiceScope`)。 IServiceScope局部容器接口 ------------ ![](https://img.tnblog.net/arcimg/hb/deac687eb9a14213a933ad35ec236712.png) tn>局部容器也同样具有与根容器的可选生命周期,它与IServiceProvider之间的关系如下图所示: ![](https://img.tnblog.net/arcimg/hb/575c97f22b6444c79427e94ad8d31778.png) ServiceProviderEngineScope局部容器类 ------------ tn>它实现了`IServiceProvider`获取服务实例接口与`IServiceScope`局部容器接口,它利用对提供服务实例的缓存实现对生命周期的控制,然后我们就可以看成: ![](https://img.tnblog.net/arcimg/hb/a5a370f67cc54eb5a305d98ebf0620a8.png) ServiceProviderEngine实例器引擎抽象类 ------------ tn>它是提供服务具体实现的核心,它通过实现`IServiceProviderEngine`让具体的实现服务实例的引擎做了抽象。具体的实现有四个类组成。在`ServiceProviderOptions`类的`Mode`属性可以指定具体的,在`BuildServiceProvider`方法的第二个参数时设置。 | | | | ------------ | ------------ | | `DynamicServiceProviderEngine` | (默认)根据请求并发数量动态决定最终的服务实例提供方案(反射和者IL Emit或者反射与表达式树,是否选择IL Emit取决于当前运行时是否支持Reflection Emit)。 | | `RuntimeServiceProviderEngine` | 采用反射的方式提供服务实例。 | | `ILEmitServiceProviderEngine` | 采用IL Emit的方式提供服务实例。 | | `ExpressionsServiceProviderEngine` | 采用表达式树的方式提供服务实例。 | tn>然后实现`IServiceScopeFactory`接口,实现创建局部容器的区域。最后用两张图来说明关系。 ![](https://img.tnblog.net/arcimg/hb/14e7876478c045aa8cca8f121c1d1526.png) ![](https://img.tnblog.net/arcimg/hb/5d0f39b349bd4b35a36b5b910c160cc3.png) tn>我可能分析得有误,但这是我的理解希望大家能指出我的问题。 扩展 ------------ tn>虽然.netcore实现了依赖注入框架,但目前还有其他的依赖框架,接下来我们来实现第三方框架的整合。 >### 适配 tn>如果要将第三发依赖注入框架,就需要解决从 `IServiceCollection` 集合到 `IServiceProvider` 对象的适配问题。 我们可以再 `IServiceCollection` 集合和 `IServiceProvider` 对象之间设置一个第三方依赖注入框架的 `ContainerBuilder` 对象。先利用包含原始的范围注册的`IServiceCollection`集合创建一个`ContainerBuilder`对象,再利用该对象构建作为依赖注入容器的`IServcieProvider`对象。 ![](https://img.tnblog.net/arcimg/hb/b0755e8637be41f8b2df66629a793f28.png) >### IServiceProviderFactory< TContainerBuilder > tn>这里泛型`TContainerBuilder`表示自定义的容器构造类`CreateBuilder`方法实现了从`IServiceCollection`构造`TContainerBuilder`的能力,`CreateServiceProvider`提供了从`TContainerBuilder`构造`IServiceProvider`的能力,最终应用程序通过接口`IServiceProvider`来获取服务,而无需进行修改。 ![](https://img.tnblog.net/arcimg/hb/a2ee525f559c4057aff1fb132872706b.png) tn>具体整合方式请参考这篇:https://www.tnblog.net/hb/article/details/5613