asp.net core 依赖注入实现全过程粗略剖析(1)
转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/
常用扩展方法 注入依赖服务:
new ServiceCollection().AddSingleton<IApplicationBuilder, ApplicationBuilder>();
// AddSingleton多个重载方法 源码
public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection services)
where TService : class
where TImplementation : class, TService
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
} return services.AddSingleton(typeof(TService), typeof(TImplementation));
} // Singleton模式 最终的调用
public static IServiceCollection AddSingleton(
this IServiceCollection services,
Type serviceType,
Type implementationType)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
} if (serviceType == null)
{
throw new ArgumentNullException(nameof(serviceType));
} if (implementationType == null)
{
throw new ArgumentNullException(nameof(implementationType));
} return Add(services, serviceType, implementationType, ServiceLifetime.Singleton);
} // 所有的Addxxx 最终都是调用Add方法,将ServiceDescriptor添加到IServiceCollection中:
private static IServiceCollection Add(
IServiceCollection collection,
Type serviceType,
Type implementationType,
ServiceLifetime lifetime)
{
var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime);
collection.Add(descriptor);
return collection;
} // IServiceCollection源码:
public interface IServiceCollection : IList<ServiceDescriptor>
{}
如上,我们一般在ConfigureService中使用Addxxx将服务注入框架的过程。大概做个总结,其实就是屌用IServiceCollection的Addxxx 扩展方法,随后调用Add方法,初始化一个ServiceDescriptor,参数是我们注入的接口和类,还有就是生命周期。随后添加到IServiceCollection中,根据该接口的定义就是一个ServiceDescriptor的集合。
我们看看ServiceDescriptor的源码:
public ServiceDescriptor(
Type serviceType,
object instance)
: this(serviceType, ServiceLifetime.Singleton)
{
if (serviceType == null)
{
throw new ArgumentNullException(nameof(serviceType));
} if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
} ImplementationInstance = instance;
}
该类就是初始化并获取如下属性:
/// <inheritdoc />
public ServiceLifetime Lifetime { get; } /// <inheritdoc />
public Type ServiceType { get; } /// <inheritdoc />
public Type ImplementationType { get; } /// <inheritdoc />
public object ImplementationInstance { get; } /// <inheritdoc />
public Func<IServiceProvider, object> ImplementationFactory { get; }
到此,我们的服务注入到asp.net core框架中就完事了,那么服务的实例化呢?
首先我们理下思路,IServiceProvider接口对应的实现是ServiceProvider,这个类就是实例化了IServiceProvider接口,而IServiceProvider接口只有一个方法:
public object GetService(Type serviceType);
该方法就是获取注入的服务。但是ServiceProvider类不单单是获取注入的服务,服务的实例化还是在该类中实现的,我们看下:
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback
{
private readonly IServiceProviderEngine _engine; private readonly CallSiteValidator _callSiteValidator; internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
{
IServiceProviderEngineCallback callback = null;
if (options.ValidateScopes)
{
callback = this;
_callSiteValidator = new CallSiteValidator();
}
switch (options.Mode)
{
case ServiceProviderMode.Dynamic:
_engine = new DynamicServiceProviderEngine(serviceDescriptors, callback);
break;
case ServiceProviderMode.Runtime:
_engine = new RuntimeServiceProviderEngine(serviceDescriptors, callback);
break;
#if IL_EMIT
case ServiceProviderMode.ILEmit:
_engine = new ILEmitServiceProviderEngine(serviceDescriptors, callback);
break;
#endif
case ServiceProviderMode.Expressions:
_engine = new ExpressionsServiceProviderEngine(serviceDescriptors, callback);
break;
default:
throw new NotSupportedException(nameof(options.Mode));
}
} /// <summary>
/// Gets the service object of the specified type.
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public object GetService(Type serviceType) => _engine.GetService(serviceType); /// <inheritdoc />
public void Dispose() => _engine.Dispose(); void IServiceProviderEngineCallback.OnCreate(IServiceCallSite callSite)
{
_callSiteValidator.ValidateCallSite(callSite);
} void IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)
{
_callSiteValidator.ValidateResolution(serviceType, scope, _engine.RootScope);
}
}
可以看到该类的构造函数中就是实例化服务的过程了。很直白的可以看出我们常见的几种方法来实例化类:反射,Emit,表达式树等...
目前也算是交代清楚了相关的类。那么框架具体是如何来实例化的呢?整个的流程是怎么样的。篇2再叙
转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/
源码地址:https://github.com/aspnet/DependencyInjection
asp.net core 依赖注入实现全过程粗略剖析(1)的更多相关文章
- asp.net core 依赖注入实现全过程粗略剖析(2)
接着 上篇 目前也算是交代清楚了相关的类.那么框架具体是如何来实例化的呢?整个的流程是怎么样的. 我们参考源码中的Test文件夹来看看: var collection = new ServiceCol ...
- asp.net core 依赖注入实现全过程粗略剖析(3)
接着 前面,前面的过程是普遍常用的依赖注入解析过程,我们正常都是在startup类中注入依赖服务,但是,笔者这周开发的时候遇到个问题,不同服务的生命周期不同,不能调用服务.举个例子,AddDbCont ...
- # ASP.NET Core依赖注入解读&使用Autofac替代实现
标签: 依赖注入 Autofac ASPNETCore ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Aut ...
- 实现BUG自动检测 - ASP.NET Core依赖注入
我个人比较懒,能自动做的事绝不手动做,最近在用ASP.NET Core写一个项目,过程中会积累一些方便的工具类或框架,分享出来欢迎大家点评. 如果以后有时间的话,我打算写一个系列的[实现BUG自动检测 ...
- [译]ASP.NET Core依赖注入深入讨论
原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...
- asp.net core 依赖注入几种常见情况
先读一篇注入入门 全面理解 ASP.NET Core 依赖注入, 学习一下基本使用 然后学习一招, 不使用接口规范, 直接写功能类, 一般情况下可以用来做单例. 参考https://www.cnblo ...
- ASP.NET Core依赖注入——依赖注入最佳实践
在这篇文章中,我们将深入研究.NET Core和ASP.NET Core MVC中的依赖注入,将介绍几乎所有可能的选项,依赖注入是ASP.Net Core的核心,我将分享在ASP.Net Core应用 ...
- 自动化CodeReview - ASP.NET Core依赖注入
自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 我个人比较懒,能自动做的事绝 ...
- ASP.NET Core 依赖注入最佳实践——提示与技巧
在这篇文章,我将分享一些在ASP.NET Core程序中使用依赖注入的个人经验和建议.这些原则背后的动机如下: 高效地设计服务和它们的依赖. 预防多线程问题. 预防内存泄漏. 预防潜在的BUG. 这篇 ...
随机推荐
- Brup Suite 渗透测试笔记(五)
之前章节记到Burp Intruder功能区,接上次笔记 一.首先说再展开说说Brup Intruder功能, 1.标识符枚举Web应用程序经常使用标识符来引用用户账户,资产数据信息. 2.提取有用的 ...
- 支付宝WAP支付总结
一:支付宝开放文档: 支付宝手机网站支付的开发文档: https://docs.open.alipay.com/203 二:配置应用环境: 开发者调用接口前需要先生成RSA2密钥,RSA2密钥包含应用 ...
- 使用7zip批量压缩文件夹到不同压缩包
for /d %%X in (*) do "c:\Program Files\7-Zip\7z.exe" a "%%X.7z" "%%X\" ...
- Docker相关释义
Docker相关释义 基础网站:http://www.runoob.com/docker/docker-tutorial.html Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上, ...
- 51Nod 1264 线段相交(计算几何)
1264 线段相交 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出平面上两条线段的两个端点,判断这两条线段是否相交(有一个公共点或有部分重合认为相 ...
- 正则 ?<= 和 ?= 用法,范例
(exp) 匹配exp,并捕获文本到自动命名的组里(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)(?:exp) 匹配exp,不捕 ...
- 三 os模块
os模块是与操作系统交互的一个接口 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录:相 ...
- C#算法 选择排序、冒泡排序、插入排序
1.冒泡排序: 方法一: public static int[] MaoPao(int[] arr) { //执行多少次 for (int i = 0; i < arr.Length; i++) ...
- layui简单例子
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- [转] 深入浅出mongoose-----包括mongoose基本所有操作,非常实用!!!!!
深入浅出mongoose mongoose是nodeJS提供连接 mongodb的一个库. 此外还有mongoskin, mongodb(mongodb官方出品). 本人,还是比较青睐mongoose ...