接着 前面,前面的过程是普遍常用的依赖注入解析过程,我们正常都是在startup类中注入依赖服务,但是,笔者这周开发的时候遇到个问题,不同服务的生命周期不同,不能调用服务。举个例子,AddDbContext注入数据库上下文,生命周期默认是scoped,但是我有个需求注入的服务是单例的,因此我注入的单利服务不能引用数据库上下文来调用数据库,最后是通过CreateScoped来解决的。因此,这篇文章说到说到CreateScoped。

public static IServiceScope CreateScope(this IServiceProvider provider)
{
return provider.GetRequiredService<IServiceScopeFactory>().CreateScope();
}

最终是由获取接口IServiceScopeFactory的服务(也就是接口的实现类),由服务调用其CreateScope方法,作为返回值。

GetRequiredService方法的最终实现:

public static object GetRequiredService(this IServiceProvider provider, Type serviceType)
{
provider.GetService(serviceType);
}

由接口IServiceProvider的实现类来获取指定的服务。
IServiceProvider接口,有三个实现类:
ServiceProviderEngineScope
ServiceProviderEngine
ServiceProvider
查看源码可知,而这三个类最终都是调用IServiceProviderEngine接口的GetService方法。该接口的实现类有多个如下:
DynamicServiceProviderEngine
RuntimeServiceProviderEngine
ILEmitServiceProviderEngine
ExpressionsServiceProviderEngine
CompiledServiceProviderEngine
ServiceProviderEngine
前五个类都是直接继承自类ServiceProviderEngine,同时这五个类的实现都是通过特定的方式来实例化指定接口,也就是返回一个接口的服务对象。
ServiceProviderEngine类的实现签名:

internal abstract class ServiceProviderEngine : IServiceProviderEngine, IServiceScopeFactory
{}

也就是说最后所有的实现都是基于IServiceProviderEngine以及IServiceScopeFactory接口。

internal interface IServiceProviderEngine : IDisposable, IServiceProvider
{
IServiceScope RootScope { get; }
}
public interface IServiceScopeFactory
{
IServiceScope CreateScope();
}

IServiceScope接口的定义:

public interface IServiceScope : IDisposable
{
IServiceProvider ServiceProvider { get; }
}

这趟下来,就获取了接口IServiceScopeFactory的服务。随后就通过服务调用CreateScope方法。上面说了继承自接口IServiceScopeFactory的类有五个,最后都是继承自ServiceProviderEngine,这里调用CreateScope方法,最后也是调用ServiceProviderEngine类的CreateScope方法。签名如下:

public IServiceScope CreateScope()
{
if (_disposed)
{
ThrowHelper.ThrowObjectDisposedException();
} return new ServiceProviderEngineScope(this);
}

返回一个接口IServiceScope的实例化类。该方法签名如下:

internal class ServiceProviderEngineScope : IServiceScope, IServiceProvider
{ }

最后我们还是调用ServiceProviderEngine类实例来调用GetService方法获取指定接口的服务。
举个实例使用的代码示例:

using (var _scope = _serviceProvider.CreateScope())
{
var _context = _scope.ServiceProvider.GetService<PracticeDevDbContext>();
}

也就是说,是用CreateScope方法来解析接口获取服务,并不是直接的调用ServiceProvider来获取接口的服务,而是通过类外的IServiceScope来
解析指定的接口获取服务,转了个弯。
那么为什么要这么实现呢?其实我并不清楚,只是遇到了一个依赖注入的问题,最后是通过如上代码解析上下文类获取数据的。后续有待研究。

asp.net core 依赖注入实现全过程粗略剖析(3)的更多相关文章

  1. asp.net core 依赖注入实现全过程粗略剖析(1)

    转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/ 常用扩展方法 注入依赖服务: new ServiceCollection().AddSingle ...

  2. asp.net core 依赖注入实现全过程粗略剖析(2)

    接着 上篇 目前也算是交代清楚了相关的类.那么框架具体是如何来实例化的呢?整个的流程是怎么样的. 我们参考源码中的Test文件夹来看看: var collection = new ServiceCol ...

  3. # ASP.NET Core依赖注入解读&使用Autofac替代实现

    标签: 依赖注入 Autofac ASPNETCore ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Aut ...

  4. 实现BUG自动检测 - ASP.NET Core依赖注入

    我个人比较懒,能自动做的事绝不手动做,最近在用ASP.NET Core写一个项目,过程中会积累一些方便的工具类或框架,分享出来欢迎大家点评. 如果以后有时间的话,我打算写一个系列的[实现BUG自动检测 ...

  5. [译]ASP.NET Core依赖注入深入讨论

    原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...

  6. asp.net core 依赖注入几种常见情况

    先读一篇注入入门 全面理解 ASP.NET Core 依赖注入, 学习一下基本使用 然后学习一招, 不使用接口规范, 直接写功能类, 一般情况下可以用来做单例. 参考https://www.cnblo ...

  7. ASP.NET Core依赖注入——依赖注入最佳实践

    在这篇文章中,我们将深入研究.NET Core和ASP.NET Core MVC中的依赖注入,将介绍几乎所有可能的选项,依赖注入是ASP.Net Core的核心,我将分享在ASP.Net Core应用 ...

  8. 自动化CodeReview - ASP.NET Core依赖注入

    自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 我个人比较懒,能自动做的事绝 ...

  9. ASP.NET Core 依赖注入最佳实践——提示与技巧

    在这篇文章,我将分享一些在ASP.NET Core程序中使用依赖注入的个人经验和建议.这些原则背后的动机如下: 高效地设计服务和它们的依赖. 预防多线程问题. 预防内存泄漏. 预防潜在的BUG. 这篇 ...

随机推荐

  1. servlet 遇到的奇怪问题

    一. servlet URl 连接多了 %09 原因value里面多了个空格 value=" value'; 改成 value="value'; 二.servlet get方法可以 ...

  2. Nginx详解十四:Nginx场景实践篇之代理服务

    代理的作用 Nginx代理 正向代理 反向代理 正向代理和反向代理的区别:代理的对象不一样 正向代理代理的对象是客户端,反向代理代理的对象是服务端 反向代理: 配置语法:proxy_pass URL; ...

  3. python字符编码和文件处理

    一.了解字符编码的知识储备 1.文本编辑器存取文件的原理(nodepad++,python,word) 打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的内容也都是存放于内存中的,断 ...

  4. HDU 1452 Happy 2004(因数和+费马小定理+积性函数)

    Happy 2004 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  5. C/C++字节序(大端/小端)判断

    C/C++大端小端判断 说的是变量的高字节.低字节在内存地址中的排放顺序. 变量的高字节放到内存的低地址中(变量的低字节放到内存的高地址中)==>大端 变量的高字节放到内存的高地址中(变量的低字 ...

  6. 【第一部分】04Leetcode刷题

    一.反转链表 II /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; ...

  7. C# float与UInt16互转

    //float拆分成两个UInt16 public static UInt16 FloatToTwoUInt16(float f) { byte[] bs = BitConvert.GetBytes( ...

  8. tomcat启动成功但是访问方面都是404

    1.开发环境与错误情况 开发环境是jdk1.7+maven+git+spring MVC+spring+mybatis+mysql. 楼主做小例子的时候发现,tomcat成功启动,但是访问主页,页面提 ...

  9. JSP基础知识➣语法整理(二)

    A.脚本程序 脚本程序可以包含任意量的Java语句.变量.方法或表达式,只要它们在脚本语言中是有效的. 脚本程序的语法格式:<% 代码片段 %>,但是不能包含文件的方法和变量的声明 B.J ...

  10. html知识杂记

    1.HTML中不支持 空格.回车.制表符,它们都会被解析成一个空白字符.2.HTML 是用来描述网页的一种语言.3.元素的内容是开始标签与结束标签之间的内容.4.即使 <br> 在所有浏览 ...