DOTNET CORE源码分析之IServiceProvider、ServiceProvider、IServiceProviderEngine、ServiceProviderEngine和ServiceProviderEngineScope
首先谈一下IServiceProvider
IServiceProvider只提供给了一个根据类型获取对象的功能,试想一下IOC总得有一个找到对象,具体如下
public interface IServiceProvider
{
object GetService(Type serviceType);
}
再谈一下ServiceProvider
ServiceProvider实例化了IServiceProvider,也就是实现了GetService,用于获取容器中实际对象,但是它是借助于IServiceProviderEngine(这个接口稍后再介绍),具体如下:
public object GetService(Type serviceType)
{
return this._engine.GetService(serviceType);
}
另外ServiceCollection中有一个方法BuildServiceProvider(存在于类ServiceCollectionContainerBuilderExtensions中),返回值对象类型就是ServiceProvider
/// <summary>
/// Extension methods for building a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> from an <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
/// </summary>
public static class ServiceCollectionContainerBuilderExtensions
{
/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(
this IServiceCollection services)
{
return services.BuildServiceProvider(ServiceProviderOptions.Default);
} /// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />
/// optionaly enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <param name="validateScopes">
/// <c>true</c> to perform check verifying that scoped services never gets resolved from root provider; otherwise <c>false</c>.
/// </param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(
this IServiceCollection services,
bool validateScopes)
{
return services.BuildServiceProvider(new ServiceProviderOptions()
{
ValidateScopes = validateScopes
});
} /// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />
/// optionaly enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <param name="options">
/// Configures various service provider behaviors.
/// </param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(
this IServiceCollection services,
ServiceProviderOptions options)
{
if (services == null)
throw new ArgumentNullException(nameof (services));
if (options == null)
throw new ArgumentNullException(nameof (options));
return new ServiceProvider((IEnumerable<ServiceDescriptor>) services, options);
}
}
必须要结合一下IServiceProviderEngine、ServiceProviderEngine和ServiceProviderEngineScope对象才能具体知道ServiceProvider是怎么获取IOC容器中的对象了
在使用BuildServiceProvider的时候,最终会调用new ServiceProvider((IEnumerable<ServiceDescriptor>)services,options),然后就是调用如下函数:
internal ServiceProvider(
IEnumerable<ServiceDescriptor> serviceDescriptors,
ServiceProviderOptions options)
{
IServiceProviderEngineCallback callback = (IServiceProviderEngineCallback) null;
if (options.ValidateScopes)
{
callback = (IServiceProviderEngineCallback) this;
this._callSiteValidator = new CallSiteValidator();
}
switch (options.Mode)
{
case ServiceProviderMode.Dynamic:
this._engine = (IServiceProviderEngine) new DynamicServiceProviderEngine(serviceDescriptors, callback);
break;
case ServiceProviderMode.Runtime:
this._engine = (IServiceProviderEngine) new RuntimeServiceProviderEngine(serviceDescriptors, callback);
break;
case ServiceProviderMode.Expressions:
this._engine = (IServiceProviderEngine) new ExpressionsServiceProviderEngine(serviceDescriptors, callback);
break;
case ServiceProviderMode.ILEmit:
this._engine = (IServiceProviderEngine) new ILEmitServiceProviderEngine(serviceDescriptors, callback);
break;
default:
throw new NotSupportedException("Mode");
}
}
就是说最终还是根据ServiceProviderMode来判断需要实例化哪种ServiceProviderEngine,现在简单举例DynamicServiceProviderEngine。DynamicServiceProviderEngine最终还是继承ServiceProviderEngine,
所以上面说的GetService其实就是调用了ServiceProviderEngine的GetService
public object GetService(Type serviceType)
{
return this.GetService(serviceType, this.Root);
}
其中this.Root就是实例化的ServiceProviderScope。上面的this.GetService(serviceType,this.Root)会调用如下函数:
internal object GetService(
Type serviceType,
ServiceProviderEngineScope serviceProviderEngineScope)
{
if (this._disposed)
ThrowHelper.ThrowObjectDisposedException();
Func<ServiceProviderEngineScope, object> orAdd = this.RealizedServices.GetOrAdd(serviceType, this._createServiceAccessor);
this._callback?.OnResolve(serviceType, (IServiceScope) serviceProviderEngineScope);
ServiceProviderEngineScope providerEngineScope = serviceProviderEngineScope;
return orAdd(providerEngineScope);
}
最终就是调用Func<ServiceProviderEngineScope, object> orAdd = this.RealizedServices.GetOrAdd(serviceType, this._createServiceAccessor);其中RealizedServices是ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>> RealizedServices { get; },this._createServiceAccessor是Func<ServiceProviderEngineScope, object>,通过这个委托根据ServiceProviderEngineScope获取最终的对象,也就是说,如果服务存在的话就从字典中获取,不存在就添加到队列上,并直接返回。另外在实例化ServiceProviderEngine的时候实例化了this._createServiceAccessor = new Func<Type, Func<ServiceProviderEngineScope, object>>(this.CreateServiceAccessor);其中CreateServiceAccessor是一个函数,定义如下:
private Func<ServiceProviderEngineScope, object> CreateServiceAccessor(
Type serviceType)
{
IServiceCallSite callSite = this.CallSiteFactory.CreateCallSite(serviceType, new CallSiteChain());
if (callSite == null)
return (Func<ServiceProviderEngineScope, object>) (_ => (object) null);
this._callback?.OnCreate(callSite);
return this.RealizeService(callSite);
}
就DynamicServiceProviderEngine而言,RealizeService的定义如下:
protected override Func<ServiceProviderEngineScope, object> RealizeService(
IServiceCallSite callSite)
{
int callCount = 0;
return (Func<ServiceProviderEngineScope, object>) (scope =>
{
if (Interlocked.Increment(ref callCount) == 2)
Task.Run<Func<ServiceProviderEngineScope, object>>((Func<Func<ServiceProviderEngineScope, object>>) (() => base.RealizeService(callSite)));
return this.RuntimeResolver.Resolve(callSite, scope);
});
}
RuntimeResolver是ServiceProviderEngine的一个属性。到此为止,IOC容器的数据就可以获取到了。下篇博客会继续说明this.RuntimeResover.Resolve下的事情。
DOTNET CORE源码分析之IServiceProvider、ServiceProvider、IServiceProviderEngine、ServiceProviderEngine和ServiceProviderEngineScope的更多相关文章
- DOTNET CORE源码分析之IOC容器结果获取内容补充
补充一下ServiceProvider的内容 可能上一篇文章DOTNET CORE源码分析之IServiceProvider.ServiceProvider.IServiceProviderEngin ...
- DOTNET CORE源码分析之ServiceDescriptor
ServiceDescriptor在.net core中的作用就是DI中注入服务元素的描述.每一个元素核心内容部分包括需要注入的服务元素的类型ServiceType,它对应的接口(如果有的话)Impl ...
- ASP.NET Core[源码分析篇] - WebHost
_configureServicesDelegates的承接 在[ASP.NET Core[源码分析篇] - Startup]这篇文章中,我们得知了目前为止(UseStartup),所有的动作都是在_ ...
- 一个由正则表达式引发的血案 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. 一些特殊字符,如“&”,“- ...
- ASP.NET Core[源码分析篇] - Authentication认证
原文:ASP.NET Core[源码分析篇] - Authentication认证 追本溯源,从使用开始 首先看一下我们通常是如何使用微软自带的认证,一般在Startup里面配置我们所需的依赖认证服务 ...
- ASP.NET Core[源码分析篇] - Startup
应用启动的重要类 - Startup 在ASP.NET Core - 从Program和Startup开始这篇文章里面,我们知道了Startup这个类的重要性,它主要负责了: 配置应用需要的服务(服务 ...
- [asp.net core 源码分析] 01 - Session
1.Session文档介绍 毋庸置疑学习.Net core最好的方法之一就是学习微软.Net core的官方文档:https://docs.microsoft.com/zh-cn/aspnet/cor ...
- ASP.NET Core[源码分析篇] - 认证
追本溯源,从使用开始 首先看一下我们的通常是如何使用微软自带的认证,一般在Startup里面配置我们所需的依赖认证服务,这里通过JWT的认证方式讲解 public void ConfigureServ ...
- EF Core 源码分析
最近在接触DDD+micro service来开发项目,因为EF Core太适合DDD模式需要的ORM设计,所以这篇博客是从代码角度去理解EF core的内部实现,希望大家能从其中学到一些心得体会去更 ...
随机推荐
- C#获取代码执行时间(精确到毫秒)
private void Time(int i) { Stopwatch sw = new Stopwatch(); sw.Start(); Thread.Sleep(i); sw.Stop(); C ...
- Java并发编程入门与高并发面试(三):线程安全性-原子性-CAS(CAS的ABA问题)
摘要:本文介绍线程的安全性,原子性,java.lang.Number包下的类与CAS操作,synchronized锁,和原子性操作各方法间的对比. 线程安全性 线程安全? 线程安全性? 原子性 Ato ...
- json/xml processing model与xml和json的简要区别
1.JavaScript Object Notation(JSON) JSON是一种轻量级数据交换格式,广泛用作通用格式,用于序列化和反序列化通过Internet相互通信的应用程序中的数据.这些应用程 ...
- TCP/IP 协议栈初识
原文:深入浅出 TCP/IP 协议栈 0. 简介 TCP/IP 协议栈是网络通信中一系列网络协议的综合,是核心骨架.它定义了电子设备接入因特网.以及数据在它们之间的传输方式,是一份标准.TCP/IP ...
- [SDOI2008] 洞穴勘测 (LCT模板)
bzoj 2049 传送门 洛谷P2147 传送门 这个大佬的LCT详解超级棒的! Link-Cut Tree的基本思路是用splay的森林维护一条条树链. splay的森林,顾名思义,就是若干spl ...
- vue子组件使用自定义事件向父组件传递数据
使用v-on绑定自定义事件可以让子组件向父组件传递数据,用到了this.$emit(‘自定义的事件名称’,传递给父组件的数据) <!DOCTYPE html> <html lang= ...
- Python测试开发-创建模态框及保存数据
Python测试开发-创建模态框及保存数据 原创: fin 测试开发社区 前天 什么是模态框? 模态框是指的在覆盖在父窗体上的子窗体.可用来做交互,我们经常会看到模态框用来登录.确定等等,到底是怎 ...
- python3.5以及scrapy,selenium,等 安装
一.python3.5安装和配置 在安装的时候无意间发现了,python3.6没有给我自定义安装的机会,直接就C盘见:因此我选择了python3.5.<安装部分跳过,至于一条吃过痛苦的建议:不要 ...
- NLP(二十二)利用ALBERT实现文本二分类
在文章NLP(二十)利用BERT实现文本二分类中,笔者介绍了如何使用BERT来实现文本二分类功能,以判别是否属于出访类事件为例子.但是呢,利用BERT在做模型预测的时候存在预测时间较长的问题.因此 ...
- C#可空类型知多少
在项目中我们经常会遇到可为空类型,那么到底什么是可为空类型呢?下面我们将从4个方面为大家剖析. 1.可空类型基础知识 顾名思义,可空类型指的就是某个对象类型可以为空,同时也是System.Nullab ...