上一篇 ASP.NET Core - 选项系统之选项配置 中提到 IOptions、IOptionsMonitor 和 IOptionsSnapshot 三个接口,通过这三个接口都可以从依赖注入容器中解析出已经配置的选项类,在我们通过 Configure 方法配置选项时,这三个接口会被同时注册,但三个接口是有区别的,适用场景也有所不同。

1. IOptions

  • IOptions 对象的生命周期是 Singleton (单例),它可以在任意地方进行注入使用
  • 该接口对象在第一次使用的时候被实例化,并且选项类中的内容会一直保持不变,前面也提过选项类内容可以在配置来源修改之后更新,但是通过 IOption 解析的选项类不会随着更新而改变
  • IOptions 接口不支持命名选项模式,它是没有 get 方法的,也并不会默认读取第一个,它只能读取 String.Empty 默认命名的选项,如果没有配置默认选项的话,虽然也能解析出 Options 选项类对象,但是对象的属性都是相应类型的默认值(引用类型是 null,值类型是 0,其他的也都是相应类型的默认值)
public class OptionController : ControllerBase
{
private readonly BlogOptions _blogOptions;
public OptionController(IOptions<BlogOptions> options)
{
// 通过 IOptions<TOptions> 接口的 Value 属性读取选项类
// 选项类始终是程序启动时加载的值,不会改变
_blogOptions = options.Value;
}
}

2. IOptionsMonitor

  • IOptionsMonitor 对象的生命周期是 Scoped(作用域),Scoped 生命周期的特点是不能注入到 Singleton 服务中
  • 在作用域中(最常见的一次Http请求),创建 IOptionsSnapshot 对象实例时,会从配置中读取最新选项值作为快照,并在当前作用域中始终使用该快照。也就是说一次请求中选项类内容保持不变,但是不同请求中可能因为配置来源的修改而不同
  • IOptionsMonitor 支持命名选项
public class OptionController : ControllerBase
{
private readonly BlogOptions _blogOptions;
public OptionController(IOptionsSnapshot<BlogOptions> optionsSnapshot)
{
// IOptionsSnapshot<TOptions> 可以通过 Value 属性读取默认的命名的选项类, Options 对象实例创建时读取的配置快照
_blogOptions = optionsSnapshot.Value;
// 也可以通过 Get 方法获取某一个命名选项,没有指定命名时,默认命名为 string.Empty
//_blogOptions = optionsSnapshot.Get(string.Empty);
}
}

3. IOptionsSnapshot

  • IOptionsSnapshot 对象的生命周期也是 Singleton (单例)
  • 通过 IOptionsSnapshot 接口注入的对象每次读取选项值时,都是从配置中读取最新选项值,能够实时获取配置来源的更改
  • 该接口支持命名选项模式
  • 除了可以查看 TOptions 的值,还可以监控 TOptions 配置的更改,支持重新加载配置(CurrentValue),并当配置发生更改时,进行通知(OnChange),支持缓存与缓存失效 (IOptionsMonitorCache),每次调用实例的 CurrentValue 时,会先检查缓存(IOptionsMonitorCache)是否有值,如果有值,则直接用,如果没有,则从配置中读取最新选项值,并记入缓存。当配置发生更改时,会将缓存清空。
public class OptionController : ControllerBase
{
private readonly BlogOptions _blogOptions;
public OptionController(IOptionsMonitor<BlogOptions> optionsMonitor)
{
// IOptionsMonitor<TOptions> 接口没有 Value 属性,通过 CurrentValue 获取选项类对象,
// 每次调用 CurrentValue都会实时读取配置源,始终是最新配置的值
_blogOptions = optionsMonitor.CurrentValue;
// 该接口也支持通过 Get 方法获取命名选项
_blogOptions = optionsMonitor.Get(string.Empty);
// 可以通过 OnChange 注册事件,当配置被加载时会触发事件
optionsMonitor.OnChange(OnOptionsChange);
} [HttpGet]
public Task<BlogOptions> Get()
{
return Task.FromResult(_blogOptions);
} private void OnOptionsChange(BlogOptions options)
{
Console.WriteLine(JsonSerializer.Serialize(options));
}
}

启动应用,调用一次 Get 接口,在 Api 控制器构造函数中注册了配置加载触发事件,之后修改 appsettings.json 配置文件中选项类对于的配置节点内容,可以看到事件触发,控制台中输出了改变之后的选项类内容。

4. 三个接口的选项读取机制演示

三个接口解析的选项类的差别,可以通过以下测试清楚得看出:

配置文件中初始选项节点如下:

"Blog": {
"Title": "ASP.NET Core Options11",
"Content": "This is a blog about Options System in ASP.NET Core Framework.",
"CreateTime": "2022-12-06"
}

这里为了方便看出 Scoped 生命周期 IOptionSnapeshoot 接口的变化,所有通过 Web Api 接口来测试

public class OptionController : ControllerBase
{
private readonly IOptions<BlogOptions> _blogOptions;
private readonly IOptionsSnapshot<BlogOptions> _blogSnapshotOptions;
private readonly IOptionsMonitor<BlogOptions> _blogMonitorOptions;
public OptionController(
IOptions<BlogOptions> options,
IOptionsSnapshot<BlogOptions> optionsSnapshot,
IOptionsMonitor<BlogOptions> optionsMonitor
)
{
// 注意这里不能再把选项类对象先读取出来,否则选项类对象也不会再改变了
_blogOptions = options;
_blogSnapshotOptions = optionsSnapshot;
_blogMonitorOptions = optionsMonitor;
} [HttpGet]
public Task Get()
{
Console.WriteLine("第一次读取配置:");
Console.WriteLine("IOptions<TOptions>:" + JsonSerializer.Serialize(_blogOptions.Value));
Console.WriteLine("IOptionsSnapshot<TOptions>:" + JsonSerializer.Serialize(_blogSnapshotOptions.Value));
Console.WriteLine("IOptionsMonitor<TOptions>:" + JsonSerializer.Serialize(_blogMonitorOptions.CurrentValue)); Console.WriteLine("请修改配置文件!");
Console.ReadKey(); Console.WriteLine("第二次读取配置:");
Console.WriteLine("IOptions<TOptions>:" + JsonSerializer.Serialize(_blogOptions.Value));
Console.WriteLine("IOptionsSnapshot<TOptions>:" + JsonSerializer.Serialize(_blogSnapshotOptions.Value));
Console.WriteLine("IOptionsMonitor<TOptions>:" + JsonSerializer.Serialize(_blogMonitorOptions.CurrentValue)); return Task.CompletedTask;
}
}

之后启动应用调用 Get 接口,并在过程中将配置文件内容修改为以下:

"Blog": {
"Title": "ASP.NET Core Options222",
"Content": "This is a blog about Options System in ASP.NET Core Framework.",
"CreateTime": "2022-12-06"
}

可以看到控制台的输出中,第二次读取配置的时候,IOptionsMonitor 接口读取到的内容已经改变

之后不要关闭应用,再调一次 Get 接口,并在过程中再次修改配置如下:

"Blog": {
"Title": "ASP.NET Core Options333",
"Content": "This is a blog about Options System in ASP.NET Core Framework.",
"CreateTime": "2022-12-06"
}

这一次的 Get 请求的输出结果如下:

可以看到 IOptionsMonitor 接口每次都能获取到配置文件的实时值,IOptionsSnapshot 接口相较于第一次调用 Get 接口的时候已经改变,获取到了之前修改的值,但是之后的修改它又获取不到了,因为它是 Scoped 生命周期,在一次请求内是保持一致的,而 IOptions 接口获取到的选项类对象是一致不变的。

参考文章:

ASP.NET Core 中的选项模式 | Microsoft Learn

选项模式 - .NET | Microsoft Learn

面向 .NET 库创建者的选项模式指南 - .NET | Microsoft Learn

理解ASP.NET Core - 选项(Options)

ASP.NET Core 系列:

目录:ASP.NET Core 系列总结

上一篇:ASP.NET Core - 选项系统之选项配置

ASP.NET Core - 选项系统之选项使用的更多相关文章

  1. .NET 黑魔法 - asp.net core 日志系统

    asp.net core 里如何记录日志呢? 这要从asp.net core的依赖注入说起,在asp.net core里的依赖注入真是无所不在,各种面向切面的接口与事件. 好吧,来点干货. 首先,我们 ...

  2. asp.net core后台系统登录的快速构建

    登录流程图 示例预览 构建步骤 当然,你也可以直接之前前往coding仓库查看源码,要是发现bug记得提醒我啊~ LoginDemo地址 1. 首先你得有一个项目 2. 然后你需要一个登录页面 完整L ...

  3. ASP.NET Core 中文文档 第三章 原理(7)配置

    原文:Configuration 作者:Steve Smith.Daniel Roth 翻译:刘怡(AlexLEWIS) 校对:孟帅洋(书缘) ASP.NET Core 支持多种配置选项.应用程序配置 ...

  4. ASP.NET Core WebListener 服务器

    原文地址:WebListener server for ASP.NET Core By Tom Dykstra, Chris Ross WebListener是一个只能运行在Windows上的ASP. ...

  5. ASP.NET Core的Kestrel服务器

    原文地址----Kestrel server for ASP.NET Core By Tom Dykstra, Chris Ross, and Stephen Halter Kestrel是一个基于l ...

  6. ASP.NET Core 认证与授权[2]:Cookie认证

    由于HTTP协议是无状态的,但对于认证来说,必然要通过一种机制来保存用户状态,而最常用,也最简单的就是Cookie了,它由浏览器自动保存并在发送请求时自动附加到请求头中.尽管在现代Web应用中,Coo ...

  7. [转帖]ASP.NET Core的Kestrel服务器

    ASP.NET Core的Kestrel服务器 https://cloud.tencent.com/developer/article/1023247 在这篇文章中: 何时使用Kestrel和反向代理 ...

  8. ASP.NET Core的Kestrel服务器(转载)

    Kestrel是一个基于libuv的跨平台ASP.NET Core web服务器,libuv是一个跨平台的异步I/O库.ASP.NET Core模板项目使用Kestrel作为默认的web服务器.Kes ...

  9. ASP.NET Core 配置文件

    在ASP.NET Core 中,应用程序配置数据可以使用JSON, XML 和 INI格式 和内置环境变量,命令行参数或内存中的集合. 1.如何获取和设置配置 ASP.NET Core配置系统针对以前 ...

  10. 3.将模型添加到 ASP.NET Core MVC 应用

    添加数据模型类 右键单击 Models 文件夹,然后单击“添加” > “类”. 将类命名“Movie”.向 Movie 类添加以下属性: using System;using System.Co ...

随机推荐

  1. 基于Face-Recognition的计算机人脸识别安全认证程序

    20202411 2020-2021-2 <Python程序设计>实验四报告 基于Face-Recognition的计算机人脸识别安全认证程序 课程:<Python程序设计> ...

  2. centos7的mysql主从

    互为主从关闭两台虚拟机的防火墙1.yum -y install mariadb-server mariadb2.Systemctl start mariadb3.进入配置文件:vi /etc/my.c ...

  3. linux资源查看与监控命令

  4. obspy常用命令记录

    如何使用obspy(适用于MAC.Linux.Windows)完全替代SAC(使用于Linux和MAC) 波形预处理 # 去均值 stream.detrend('demean') # 去线性趋势 st ...

  5. maven资源导出问题

    <!--在build中配置resources,来防止我们资源导出失败的问题--> <build> <resources> <resource> < ...

  6. OO课程第一阶段(前三次作业)总结Blog1

    OO课程第一阶段(前三次作业)总结Blog1 前言:学习OOP课程的第一阶段已经结束了,在此进行对于知识点,题量,难度的个人看法. (1)相比于另外两次作业,第一次作业基本上是基本的编程的语法训练,题 ...

  7. 解决IOS上传竖向照片会旋转90度的问题

    // 解决IOS上传竖向照片会旋转90度的问题 rotate() { const that = this; that.imgOrientation = 1; let Orientation = nul ...

  8. 11.30linux学习第十一天

    今天老刘上课,第7章收尾,第8章开了个头. 7.1.3  磁盘阵列+备份盘 RAID 10磁盘阵列中最多允许50%的硬盘设备发生故障,但是存在这样一种极端情况,即同一RAID 1磁盘阵列中的硬盘设备若 ...

  9. 浙里办微信小程序总结

    浙里办微信小程序单点登录流程 1.获取浙里办跳转地址中ticket或者微信小程序中的ticketId let ticket = getQueryString("ticket", w ...

  10. Linux配置

    JDK安装 一.登录虚拟机进入终端切换到root用户,输入:su 接着输入密码 再输入:cd - 回到root用户 二.接着在终端进入对应文件新建一个装jdk包的文件夹,输入:mkdir +目录名称 ...