生命周期策略

在实例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 中的依赖注入的深入理解)的更多相关文章

  1. ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings

    问: ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings 答: Dependency injection is possible in filters as ...

  2. 在.NET Core控制台程序中使用依赖注入

    之前都是在ASP.NET Core中使用依赖注入(Dependency Injection),昨天遇到一个场景需要在.NET Core控制台程序中使用依赖注入,由于对.NET Core中的依赖注入机制 ...

  3. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  4. ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【解读ServiceCallSite 】

    通过上一篇的介绍我们应该对实现在ServiceProvider的总体设计有了一个大致的了解,但是我们刻意回避一个重要的话题,即服务实例最终究竟是采用何种方式提供出来的.ServiceProvider最 ...

  5. NET Core 中的依赖注入

    NET Core 中的依赖注入 [共7篇] 一.控制反转(IoC) ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制, ...

  6. .NET CORE——Console中使用依赖注入

    我们都知道,在 ASP.NET CORE 中通过依赖注入的方式来使用服务十分的简单,而在 Console 中,其实也只是稍微绕了个小弯子而已.不管是内置 DI 组件或者第三方的 DI 组件(如Auto ...

  7. Asp.net core中的依赖注入

    使用服务 在Asp.net core的Controller中,可以通过如下两种方式获取系统注入的服务: 构造函数 可以直接在构造函数中传入所依赖的服务,这是非常常见的DI注入方式. public Va ...

  8. ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)

    在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...

  9. ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入

    原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...

  10. Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

随机推荐

  1. 闭关修炼180天----吐血整理MongoDB的学习笔记

    MongoDB 一.MongoDB体系结构 1.1 mongoDB和NoSql mongoDB是一种NoSql,是文档存储的代表. mongoDB是一个基于分布式文件存储的数据库.为web应用提供可扩 ...

  2. C++ Qt开发:QNetworkAccessManager网络接口组件

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QNe ...

  3. idea 暂存 Stash Changes Git/Repository/Stash Changes 恢复暂存 UnStash Changes

    idea 暂存 Stash Changes Git/Repository/Stash Changes 恢复暂存 UnStash Changes git stash save "save me ...

  4. Android USB开发1—开发环境搭建

    通过Genymotion 与 VirtualBox 可以实现将电脑中的USB设备转接到Android模拟器中进行通信. Genymotion 配置 首先从https://www.genymotion. ...

  5. gcc生成静态链接库与动态链接库步骤,并链接生成可执行文件的简单示例

    编写 mylib.h void test(); 编写 mylib.c #include<stdio.h> void test(){ printf("hello world&quo ...

  6. 新闻新体验!3DCAT助力开启红网“元宇宙”新闻直播间

    2022年10月20日,湖南红网新媒体集团"华章·20--红网时刻新闻党的二十大报道云展厅"正式上线.深入到新闻元宇宙,开拓新的传播领域,这也是红网党政新媒体元宇宙传播应用实验室的 ...

  7. 崩溃bug日志总结3

    目录介绍 1.1 OnErrorNotImplementedException[ Can't create handler inside thread that has not called Loop ...

  8. 三维模型3DTile格式轻量化的跨平台兼容性问题分析

    三维模型3DTile格式轻量化的跨平台兼容性问题分析 三维模型3DTile格式是一种开放的.高效的和互操作的空间信息数据格式.然而,它作为一种新兴的技术,其在轻量化与跨平台兼容性方面存在着一些问题. ...

  9. iOS模拟器 Unable to boot the Simulator —— Ficow笔记

    本文首发于 Ficow Shen's Blog,原文地址: iOS模拟器 Unable to boot the Simulator -- Ficow笔记. 内容概览 前言 终结模拟器进程 命令行改权限 ...

  10. 鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)

    一.RelativeContainer 1.概述 ArkUI组件中的RelativeContainer是一个相对定位的容器,可以用来将子组件按照相对位置布局. 在RelativeContainer中, ...