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. 这篇 ...
随机推荐
- 水果(map的嵌套)
夏天来了~~好开心啊,呵呵,好多好多水果~~ Joe经营着一个不大的水果店.他认为生存之道就是经营最受顾客欢迎的水果.现在他想要一份水果销售情况的明细表,这样Joe就可以很容易掌握所有水果的销售情况了 ...
- 【python】threadpool的内存占用问题
先说结论: 在使用多线程时,不要使用threadpool,应该使用threading, 尤其是数据量大的情况.因为threadpool会导致严重的内存占用问题! 对比threading和threadp ...
- Java 并发类
java.util.concurrent包里 提供了一批线程安全的类 一. java.util.concurrent.atomic java.util.concurrent.atomic包里的原子处理 ...
- 2017-2018-2 20165314实验二《Java面向对象程序设计》实验报告
实验报告封面 实验一 实验要求 参考 http://www.cnblogs.com/rocedu/p/6371315.html#SECUNITTEST 完成单元测试的学习提交最后三个JUnit测试用例 ...
- this容易混淆的示例
[注]this 永远不会混乱,混乱的是我们而已. /* this永远指向当前函数的主人. this混乱: 1.添加了定时器/延时器 2.事件绑定 [注]函数如果发生了赋值,this就混乱了. */ 示 ...
- 繁简字转换(C#)
1.首先引入: using Microsoft.VisualBasic; 2.转换方法: //繁体转简体 public static string Traditional2Simplified(str ...
- Java接口自动化测试之TestNG测试报告ExtentReports的应用(三)
pom.xml导入包 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...
- IDEA项目的复制操作
另一种复制项目的方法 完成
- 转: 解压Assets.car (iOS加密资源)
今天想获取APP的资源,但是查看xxx.app文件夹里面,缺少了大部分资源.在文件夹里面发现Assets.car这个文件,发现文件很大有40多M,猜想图片资源会不会被压缩到这里面了,所以就网络上查了下 ...
- 在th中显示图片
从DataTable中获取值: foreach (DataRow dr in ((DataTable)ViewBag.bookInfoList).Rows) { <tr> <th c ...