重新整理.net core 计1400篇[八] (.net core 中的依赖注入的深入理解)
生命周期策略
在实例Transient 和 Scoped 中,所以实现Idisposable 接口的服务实例会被当前IServiceProvider 对象保存起来,当IService 对象的Dispose 方法被调用的时候,这些服务实例的Dispose 方法被随着调用。
在singleton由于服务实例保存在根容器的IserviceProvide 对象上,所以只有当后者的Dispose方法被调用的时候,这些服务实例的Dispose方法才会随之被调用。
在.net core 应用中,他具有一个与当前应用绑定代表的全局根容器的IServiceProvider对象。对于处理的每一次请求,ASP.Net Core框架会利用这个根容器来创建基于当前请求的服务范围,并利用后者提供的IServiceProvider对象来提供请求处理所需的服务实例。
请求处理完成之后,创建的服务范围被终结,那么会调用IDisposable让其他服务实例得到释放。
服务注册的验证
为什么服务注册需要验证呢?
对于singleton和scoped 两种不同生命周期是通过将提供的服务实例分别存放到作为根容器的IServiceProvider对象和当前的IServiceProvider 对象来实现的。
这意味着作为根容器提供的Scoped也是单例的。
在asp.net core应用中,将某个服务注册的生命周期设置为Scoped的真正意图是希望依赖注入容器根据接收的每个请求来创建和释放服务实例,但是一旦一个singleton引用了一个scoped,那么scoped将会变成一个singleton。
可能这样说有些模糊,代码来示范一下:
static void Main()
{
var root = new ServiceCollection()
.AddSingleton<IFoo, Foo>()
.AddScoped<IBar, Bar>()
.BuildServiceProvider(true);
var child = root.CreateScope().ServiceProvider;
void ResolveService<T>(IServiceProvider provider)
{
var isRootContainer = root == provider ? "Yes" : "No";
try
{
provider.GetService<T>();
Console.WriteLine($"Status: Success; Service Type: { typeof(T).Name}; Root: { isRootContainer}");
}
catch (Exception ex)
{
Console.WriteLine($"Status: Fail; Service Type: { typeof(T).Name}; Root: { isRootContainer}");
Console.WriteLine($"Error: {ex.Message}");
}
}
ResolveService<IFoo>(root);
ResolveService<IBar>(root);
ResolveService<IFoo>(child);
ResolveService<IBar>(child);
Console.ReadKey();
}
public interface IFoo { }
public interface IBar { }
public class Foo : IFoo
{
public IBar Bar { get; }
public Foo(IBar bar) => Bar = bar;
}
public class Bar : IBar { }
是这样的一个故事,在Foo中是一个单例,因为Foo引用了Bar,那么再Foo中Bar就是一个单例了。
上面有一个方法:.BuildServiceProvider(true);,设置为true,那么这个时候就会验证Scoped模式是不是就真的就是scoped。
结果为:
实际上,服务范围的校验中,是根据一个叫做ServiceProviderOptions来做设置的,刚刚我们设置的是ValidateScopes,也就是校验范围,但是这个校验范围是在我们创建服务实例的时候校验的,那么能不能在我们注册的时候就校验呢?
/// <summary>
/// Options for configuring various behaviors of the default <see cref="T:System.IServiceProvider" /> implementation.
/// </summary>
public class ServiceProviderOptions
{
internal static readonly ServiceProviderOptions Default = new ServiceProviderOptions();
/// <summary>
/// <c>true</c> to perform check verifying that scoped services never gets resolved from root provider; otherwise <c>false</c>. Defaults to <c>false</c>.
/// </summary>
public bool ValidateScopes
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}
/// <summary>
/// <c>true</c> to perform check verifying that all services can be created during <code>BuildServiceProvider</code> call; otherwise <c>false</c>. Defaults to <c>false</c>.
/// NOTE: this check doesn't verify open generics services.
/// </summary>
public bool ValidateOnBuild
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}
internal ServiceProviderMode Mode
{
[CompilerGenerated]
get;
[CompilerGenerated]
set;
}
}
可以看到还有一个属性,ValidateOnBuild,这个显示当在构造的时候就会被验证。
举例子:
static void Main()
{
BuildServiceProvider(false);
BuildServiceProvider(true);
void BuildServiceProvider(bool validateOnBuild)
{
try
{
var options = new ServiceProviderOptions
{
ValidateOnBuild = validateOnBuild
};
new ServiceCollection()
.AddSingleton<IFoobar, Foobar>()
.BuildServiceProvider(options);
Console.WriteLine($"Status: Success; ValidateOnBuild: {validateOnBuild}");
}
catch (Exception ex)
{
Console.WriteLine($"Status: Fail; ValidateOnBuild: {validateOnBuild}");
Console.WriteLine($"Error: {ex.Message}");
}
}
Console.Read();
}
结果为:
也就是说在注册服务的时候就会报错。
总结
后面介绍服务注册的一些细节。
重新整理.net core 计1400篇[八] (.net core 中的依赖注入的深入理解)的更多相关文章
- ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings
问: ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings 答: Dependency injection is possible in filters as ...
- 在.NET Core控制台程序中使用依赖注入
之前都是在ASP.NET Core中使用依赖注入(Dependency Injection),昨天遇到一个场景需要在.NET Core控制台程序中使用依赖注入,由于对.NET Core中的依赖注入机制 ...
- ASP.NET Core中的依赖注入(2):依赖注入(DI)
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...
- ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【解读ServiceCallSite 】
通过上一篇的介绍我们应该对实现在ServiceProvider的总体设计有了一个大致的了解,但是我们刻意回避一个重要的话题,即服务实例最终究竟是采用何种方式提供出来的.ServiceProvider最 ...
- NET Core 中的依赖注入
NET Core 中的依赖注入 [共7篇] 一.控制反转(IoC) ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制, ...
- .NET CORE——Console中使用依赖注入
我们都知道,在 ASP.NET CORE 中通过依赖注入的方式来使用服务十分的简单,而在 Console 中,其实也只是稍微绕了个小弯子而已.不管是内置 DI 组件或者第三方的 DI 组件(如Auto ...
- Asp.net core中的依赖注入
使用服务 在Asp.net core的Controller中,可以通过如下两种方式获取系统注入的服务: 构造函数 可以直接在构造函数中传入所依赖的服务,这是非常常见的DI注入方式. public Va ...
- ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)
在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...
- ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入
原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...
- Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
随机推荐
- VC-MFC 登陆界面 + 数据库账号+密码
1 // DlgUser.cpp : 实现文件 2 // 3 4 #include "stdafx.h" 5 #include "Login.h" 6 #inc ...
- URL(网址)的组成
URL(Uniform Resource Locator,统一资源定位器)就是通常所说的"网址".它是用来标识互联网上资源(如网页.图片.文件等)的唯一地址.URL由协议(如htt ...
- centos7 开机自动执行脚本
1.因为在centos7中/etc/rc.d/rc.local的权限被降低了,所以需要赋予其可执行权 chmod +x /etc/rc.d/rc.local 2.赋予脚本可执行权限假设/usr/loc ...
- iview viewDesign table 单选 Radio
columns.js export default [ { title: '选择', slot: 'choose', align: 'center', width: 100 }, table里面 &l ...
- Github下载release附件变相提速方法
最近找到了个油猴插件,下载2M/s,推荐大家使用Github 镜像访问,加速下载 描述 github上面有许多开源的软件,作者们都打包发布为release版本,我们可以下载打包好的软件,但是,由于国内 ...
- js实现回调功能实例
所谓js回调,本人认为无非就是一个函数的参数是另外一个函数,而作为参数的函数就称之为回调函数 <script type="text/javascript"> //要请 ...
- 杂谈之WEB前端工程师身价
了解javascript语言规范么?+1000 知道各浏览器的css差异么?+1000 javascript差异呢?+1000 知道html各标签的含义并很好地运用么?+1000 知道如何跨浏览器解决 ...
- enum class 用法
enum的主要缺点 1.类型不明确 首先,无法指定数据类型,导致我们无法明确枚举类型所占的内存大小.这种麻烦在结构体当中尤为突出,特别是当我们需要内存对齐和填充处理的时候. #include < ...
- K8S-1.23.17+Ceph+KubeSphere 一主二从部署攻略
K8S部署攻略 此教程以一主二从为例,需要三台服务器. 主机最低需求: 4 核 CPU,4 GB 内存,硬盘:20 GBx2 (需保留一个未分区的磁盘) 从机最低需求: 4 核 CPU,8 GB 内存 ...
- Android 开发Day10
这是main里面的所有代码,按版本修改过 AndroidManifest.xml <?xml version="1.0" encoding="utf-8" ...