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 

DependencyInjection源码解读之ServiceProvider的更多相关文章

  1. swoft 源码解读【转】

      官网: https://www.swoft.org/ 源码解读: http://naotu.baidu.com/file/814e81c9781b733e04218ac7a0494e2a?toke ...

  2. Lumen开发:lumen源码解读之初始化(4)——服务提供(ServiceProviders)与路由(Routes)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 前面讲了singleton和Middleware,现在来继续讲ServiceProviders和Routes,还是看起始文件bootstrap/a ...

  3. Abp 审计模块源码解读

    Abp 审计模块源码解读 Abp 框架为我们自带了审计日志功能,审计日志可以方便地查看每次请求接口所耗的时间,能够帮助我们快速定位到某些性能有问题的接口.除此之外,审计日志信息还包含有每次调用接口时客 ...

  4. AspNetCore7.0源码解读之UseMiddleware

    Use​Middleware​Extensions 前言 本文编写时源码参考github仓库主分支. aspnetcore提供了Use方法供开发者自定义中间件,该方法接收一个委托对象,该委托接收一个R ...

  5. SDWebImage源码解读之SDWebImageDownloaderOperation

    第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...

  6. SDWebImage源码解读 之 NSData+ImageContentType

    第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...

  7. SDWebImage源码解读 之 UIImage+GIF

    第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...

  8. SDWebImage源码解读 之 SDWebImageCompat

    第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...

  9. SDWebImage源码解读_之SDWebImageDecoder

    第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...

随机推荐

  1. python 使用 thrift 教程

    一.前言: Thrift 是一种接口描述语言和二进制通信协议.以前也没接触过,最近有个项目需要建立自动化测试,这个项目之间的微服务都是通过 Thrift 进行通信的,然后写自动化脚本之前研究了一下. ...

  2. .Net语言 APP开发平台——Smobiler学习日志:SmoOne新增考勤功能

    大家好!SmoOne这次新增了考勤功能,大家打开SmoOne应用便可体验,无需重新下载更新.如果没有下载SmoOne客户端,可以在apps.smobiler.com进行下载安装. 另外,SmoOne开 ...

  3. 第48章 UserInfo端点(UserInfo Endpoint) - Identity Server 4 中文文档(v1.0.0)

    UserInfo端点可用于检索有关用户的身份信息(请参阅规范). 调用者需要发送代表用户的有效访问令牌.根据授予的范围,UserInfo端点将返回映射的声明(至少需要openid作用域). 示例 GE ...

  4. [MySQL] explain中的using where和using index

    1. 查看表中的所有索引 show index from modify_passwd_log;  有两个 一个是id的主键索引 , 一个是email_id的普通索引 2. using index表示 ...

  5. [日常] imap协议读取邮件

    telnet imap.sina.net 143 A01 LOGIN shihan@appdev.sinanet.com 密码 A02 list "" * //列出邮件夹 * LI ...

  6. 委托(3).net 2.0中的委托

    由于.net 2.0引入了匿名方法,所以创建委托的方式可以更简化了. .net 2.0中的委托 有了匿名方法,上一篇的例子可以简化为: namespace DelegateDemo { //声明委托 ...

  7. C#设计模式之二工厂方法模式(Factory Method Pattern)【创建型】

    一.引言 在上一篇文章中我们讲解了过渡的一种模式叫做[简单工厂],也有叫[静态工厂]的,通过对简单工厂模式得了解,我们也发现了它的缺点,就是随着需求的变化我们要不停地修改工厂里面的方法的代码,需求变化 ...

  8. vue 新版本 webpack 代理 跨域设置

    旧版本中:dev-server.js 这段去掉 var apiRoutes = express.Router() //getList apiRoutes.get('/getDiscList', fun ...

  9. Scrapped or attached views may not be recycled

    在使用recycleView的时候出现了错误Scrapped or attached views may not be recycled 原因: view没有被recycled,recyclerVie ...

  10. Android获取定位权限,获取设备所在的经纬度

    转载请标明出处:http://www.cnblogs.com/tangZH/p/8969898.html  前言: 有时候我们仅仅是想要获取设备所在的经纬度,那么直接调用Android相关的api就可 ...