ServiceCollection、ServiceDescriptor、ServiceLifetime、IServiceProvider

Microsoft.Extensions.DependencyInjection.Abstractions

Microsoft.Extensions.DependencyInjection

基础使用方式
class Car : ICar { }
interface ICar { }
IServiceCollection services = new ServiceCollection();
ServiceDescriptor transientService = new ServiceDescriptor(typeof(ICar), typeof(Car), ServiceLifetime.Transient);
services.Add(transientService);
services.AddTransient<ICar, Car>();
var serviceProvider = services.BuildServiceProvider();
var car = serviceProvider.GetService(typeof(ICar));
IServiceCollection

存放服务注册的集合

ServiceCollection

它是对IServiceCollection接口的默认实现,

核心属性private readonly List<ServiceDescriptor> _descriptors = new List<ServiceDescriptor>();可以说是对List的一个包装类。

ServiceLifetime

用于描述服务声明周期的枚举 Singleton、Scoped、Transient

ServiceDescriptor

用于描述服务的注册信息

属性,后三个为提供的的服务实际类有关。

  1. ServiceType服务类型
  2. Lifetime生命周期
  3. Type ImplementationType
  4. Func<IServiceProvider,object> ImplementationFactory
  5. object ImplementationInstance

它还提供了一系列静态方法供用于创建ServiceDescriptor

  1. ServiceDescriptor.Transient

    transientService = ServiceDescriptor.Transient(typeof(ICar), typeof(Car));
  2. ServiceDescriptor Describe

    例如ServiceDescriptor.Transient

    transientService = ServiceDescriptor.Describe(typeof(ICar), typeof(Car), ServiceLifetime.Transient);

多数情况下是使用ServiceCollectionServiceExtensions为IServiceCollection扩展的一系列方法添加服务到IServiceCollection集合。

ServiceCollectionServiceExtensions

作为IServiceCollection提供了一系列添加服务注册信息到IServiceCollection集合集合内,内部基本都是创建对应的ServiceDescriptor然后调用IServiceCollection.Add方法添加到集合内。

IServiceProviderFactory

IServiceProvider的工厂接口默认实现为DefaultServiceProviderFactory

DefaultServiceProviderFactory

IServiceProvider的工厂类

构造函数

  1. public DefaultServiceProviderFactory() : this(ServiceProviderOptions.Default)
  2. public DefaultServiceProviderFactory(ServiceProviderOptions options)

    两个方法
  3. public IServiceCollection CreateBuilder(IServiceCollection services)
  4. public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder) 它的内部CreateServiceProvider也是调用的ServiceCollectionContainerBuilderExtensions提供的扩展方法。
ServiceCollectionContainerBuilderExtensions

对IServiceCollection的扩展作用就是创建IServiceProvider例如提供了BuildServiceProvider

IServiceProvider

仅有的一个方法为用于获取服务。object? GetService(Type serviceType);ServiceProvider是它的默认实现ServiceProvider`

ServiceProviderOptions
  1. ValidateScopes 验证服务之前的Scopes依赖:例如 Singleton 服务依赖另一个Scoped服务,那么这个Scoped服务实例将被一个Singleton服务实例所引用,这时候此Scoped服务实例成了一个Singleton服务实例,如果设置为True ServiceProvider的构造方法内会创建一个CallSiteValidator对象给自己的_callSiteValidator属性。 验证动作会在当Provider获取到CallSiteSerivce后对其进行验证。

  2. ValidateOnBuild IServiceProvider 对象被构建的时候会检验提供的每个ServiceDescriptor 的有效性 例如注册的Car 没有一个可以用的构造函数 class Car : ICar { private Car() { } }的情况 。如果设置为True此时在buildServicePrivate时会抛出异常,否则需要等GetService时才会抛出异常。这是因为这个验证是在CallSiteFactory.GetCallSite动作里面做的,当设置为true是 也只是在ServiceProvider构造函数内调用了ValidateService方法该方法循环调用CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain),也就是说把,ServiceCallSite的创建动作提前。注意GetCallSite是个重载方法。具体区别会写在CallSiteFactory章节

Net6 DI源码分析Part1 ServiceCollection、ServiceDescriptor、ServiceLifetime、IServiceProvider的更多相关文章

  1. Net6 DI源码分析Part5 在Kestrel内Di Scope生命周期是如何根据请求走的?

    Net6 DI源码分析Part5 在Kestrel内Di Scope生命周期是如何根据请求走的? 在asp.net core中的DI生命周期有一个Scoped是根据请求走的,也就是说在处理一次请求时, ...

  2. Net6 DI源码分析Part4 CallSiteFactory ServiceCallSite

    Net6 CallSiteFactory ServiceCallSite, CallSiteChain abstract class ServiceCallSite ServiceCallSite是个 ...

  3. Net6 DI源码分析Part2 Engine,ServiceProvider

    ServiceProvider ServiceProvider是对IServiceProvider实现,它有一个internal的访问修饰符描述的构造,并需要两个参数IServiceCollectio ...

  4. Net6 DI源码分析Part3 CallSiteRuntimeResolver,CallSiteVisitor

    CallSiteRuntimeResolver CallSiteRuntimeResolver是实现了CallSiteVisitor之一. 提供的方法主要分三个部分 自有成员方法 Resolve提供服 ...

  5. Net6 Configuration & Options 源码分析 Part1

    Net6 Configuration & Options 源码分析 Part1 在Net6中配置系统一共由两个部分组成Options 模型与配置系统.它们是两个完全独立的系统. 第一部分主要记 ...

  6. 小白都能看懂的 Spring 源码揭秘之依赖注入(DI)源码分析

    目录 前言 依赖注入的入口方法 依赖注入流程分析 AbstractBeanFactory#getBean AbstractBeanFactory#doGetBean AbstractAutowireC ...

  7. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  8. Net6 Configuration & Options 源码分析 Part2 Options

    Net6 Configuration & Options 源码分析 Part2 Options 第二部分主要记录Options 模型 OptionsConfigurationServiceCo ...

  9. 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器

    1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...

随机推荐

  1. Gumbel distribution

    目录 概 主要内容 定义 Gumbel-Max trick Gumbel trick 用于归一化 代码 概 感觉这个分布的含义很有用啊, 能预测'最大', 也就是自然灾害, 太牛了. 主要内容 定义 ...

  2. [数据结果]C语言 基础指令汇编

    数据结构 C语言核心操作集合 (1)预定义常量和类型 //函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #d ...

  3. <数据结构>由SearchTree的遍历序列确定树

    目录 XDOJ315. 拓展先序遍历-->二叉树 问题与解答 题后反思:数组树的不足 XDOJ318.先序+中序-->二叉树 问题与解答 题后反思:左右子树赋零 XDOJ320.层序+中序 ...

  4. JSP中使用<c:forEach>标签循环遍历元素

    1.forEach标签元素 <c:forEach items="接收集合对象" var="迭代参数名称" varStatus="迭代状态,可访问 ...

  5. Java面向对象笔记 • 【第5章 异常处理】

    全部章节   >>>> 本章目录 5.1 异常概述 5.1.1 程序中的异常 5.1.2 异常分类 5.1.3 实践练习 5.2 try-catch处理异常 5.2.2 使用f ...

  6. 关于linux的一点好奇心(一):linux启动过程

    一直很好奇,操作系统是如何工作的?我们知道平时编程,是如何让代码跑起来的,但那些都是比较高层次的东西.越往后,你会越觉得,像是空中楼阁,或者说只是有人帮你铺平了许多道理,而你却对此一无所知. 1. 操 ...

  7. shell2-if判断2

    1.条件判断if 判断条件:then //单分支语句 命令1 命令2fi 例子: #!/bin/bash ls if [ $? -eq 0 ]; then echo "执行成功了" ...

  8. Typescript Record的用法

    Record<Keys,Type> 构造一个对象类型,其属性key是Keys,属性value是Tpye.被用于映射一个类型的属性到另一个类型 interface CatInfo { age ...

  9. Flask_cookie和session(五)

    一.cookie和session介绍 cookie 在网站中,http请求是无状态的.也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户.cookie的出现 ...

  10. Shell统计每个单词出现的个数

    题目链接 题目描述 写一个 bash脚本以统计一个文本文件 nowcoder.txt 中每个单词出现的个数. 为了简单起见,你可以假设: nowcoder.txt只包括小写字母和空格. 每个单词只由小 ...