本文将介绍 ASP.NET Core 中的 Options 概念和使用方法。Options 是一种配置管理机制,可以将应用程序的配置信息从代码中分离出来,提高代码的可维护性和可测试性。我们将详细介绍如何定义 Options 类、注册 Options、使用 Options,并提供相应的示例代码。此外,我们还将对 IOptions、IOptionsSnapshot、IOptionsMonitor、IConfigureNamedOptions、OptionsBuilder、IValidateOptions、PostConfigureOptions 等相关接口和类进行说明,并给出使用场景示例。

Options 概述

在 ASP.NET Core 中,Options 是一种配置管理机制,它允许将应用程序的配置信息从代码中分离出来,以提高代码的可维护性和可测试性。通过使用 Options,我们可以将配置信息封装到一个或多个 Options 类中,并通过依赖注入将其注入到需要使用配置的组件中。

Options 提供了一种统一的方式来访问配置信息,而不需要直接访问配置文件或配置提供程序。它还支持配置的热更新,即在应用程序运行时修改配置后,可以自动应用新的配置值,而无需重新启动应用程序。

定义 Options 类

在 ASP.NET Core 中,我们可以通过定义一个 Options 类来表示一组相关的配置信息。Options 类是一个普通的 C# 类,其中的属性对应配置的键值对。

public class MyOptions
{
public string Option1 { get; set; }
public int Option2 { get; set; }
}

在上面的示例中,我们定义了一个名为 MyOptions 的 Options 类,它包含了两个属性 Option1 和 Option2。
在appsettings.json中添加配置:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MyOptions": {
"Option1": "Test",
"Option2": 123
}
}

注册 Options

要在 ASP.NET Core 中使用 Options,我们需要将 Options 类注册到依赖注入容器中。可以通过在 ConfigureServices 方法中调用 services.Configure(Configuration.GetSection("SectionName")) 来完成注册。

public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));
}

使用WebApplication则这样操作:

builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));

在上面的示例中,我们将 MyOptions 类注册为一个 Options,并指定了配置文件中的配置节名称为 "MyOptions"。

使用 Options

在需要使用配置的组件中,我们可以通过依赖注入将 Options 注入,并直接访问 Options 类的属性来获取配置值。

public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
}; private readonly MyOptions _options;
private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger, MyOptions options)
{
_logger = logger;
_options = options;
} [HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
// 使用配置值
var option1Value = _options.Option1;
var option2Value = _options.Option2;
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}

在上面的示例中,我们通过构造函数注入了 IOptions,并在 WeatherForecastController中使用了配置值。

通过Debug我们可以看到正常获取值。

IOptions、IOptionsSnapshot 和 IOptionsMonitor

在 ASP.NET Core 中,有三个主要的 Options 接口:IOptions、IOptionsSnapshot 和 IOptionsMonitor,它们在不同的场景下提供了不同的配置值获取方式。
IOptions:在每次调用时返回相同的配置值,适用于获取配置值后不会发生变化的场景。
IOptionsSnapshot:在每次调用时返回最新的配置值,适用于获取配置值可能会发生变化的场景。
IOptionsMonitor:实时监控配置值的变化,并在配置值发生变化时提供新的配置值,适用于需要实时响应配置变化的场景。
下面我们把Options分三种模式注入。

public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
}; private readonly MyOptions _options;
private readonly MyOptions _options2;
private MyOptions _options3;
private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger, IOptions<MyOptions> options, IOptionsSnapshot<MyOptions> options2, IOptionsMonitor<MyOptions> options3)
{
_logger = logger;
_options = options.Value;
_options2 = options2.Value;
_options3 = options3.CurrentValue;
options3.OnChange(o => _options3 = options3.CurrentValue);
} [HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
// 使用配置值
var option1Value = _options.Option1;
var option2Value = _options.Option2;
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}

首次请求,可以看到三个内容都是一致的

接下来修改一下配置文件,注意,不需要重启服务。

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MyOptions": {
"Option1": "Test2222",
"Option2": 123456
}
}

再次请求,可以看到IOptionsSnapshot和IOptionsMonitor都发生了变化。




这里我们可以看到IOptionsMonitor获取内容不是Value,而是CurrentValue,因为他是实时发生更新变化的。如果我们也需要试试获取最新变化的值,则可以使用OnChange监听变化,然后重新给属性赋值。
比如我们跑的后台任务,或者一些单例服务,在第一次构造器注入options之后就不会变化的场景,可以用这种方式的更新Options的值。

IConfigureNamedOptions、OptionsBuilder 和 IValidateOptions

IConfigureNamedOptions:用于配置特定名称的 Options 对象。可以通过实现该接口来为特定的 Options 类提供配置。
比如:

builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));
builder.Services.Configure<MyOptions>("Abcd",builder.Configuration.GetSection("MyOptions"));

OptionsBuilder:用于配置 Options 对象。可以通过调用 Configure 方法来为 Options 类进行配置。

builder.Services.AddOptions<MyOptions>("OptionsBuilderOptions")
.Configure(o =>
{
o.Option1 = "OptionsBuilderOptions";
o.Option2 = 999;
})
;

启动服务DEBUG检验一下,发现我们成功取到值了。

这里需要注意的是IOptions<>是没有Get的方法的,要获取对应名称的Options只能通过IOptionsSnapshot<>或IOptionsMonitor<>。

IValidateOptions:用于验证 Options 对象的配置。可以通过实现该接口来对 Options 进行验证。

public class MyOptionsValidator : IValidateOptions<MyOptions>
{
public ValidateOptionsResult Validate(string name, MyOptions options)
{
// 验证 Options 的配置
if (options.Option1 == null)
{
return ValidateOptionsResult.Fail("Option1 must be specified.");
}
return ValidateOptionsResult.Success;
}
}
builder.Services.AddOptions<MyOptions>("ValidateOptions")
.Configure(o =>
{
o.Option1 = null;
o.Option2 = 999;
})
;
builder.Services.AddSingleton<IValidateOptions
<MyOptions>, MyOptionsValidateOptions>();
public WeatherForecastController(ILogger<WeatherForecastController> logger, IOptions<MyOptions> options, IOptionsSnapshot<MyOptions> options2, IOptionsMonitor<MyOptions> options3)
{
_logger = logger;
_options = options.Value;
_options2 = options2.Value;
_options3 = options3.CurrentValue;
options3.OnChange(o => _options3 = options3.CurrentValue); var nameOption = options2.Get("Abcd");
var nameOption2 = options3.Get("OptionsBuilderOptions");
var nameOption3 = options3.Get("ValidateOptions");
}

启动服务,发出请求,可以发现报错了。

结论

通过合理使用 Options,我们可以更好地管理和配置 ASP.NET Core 应用程序。本文详细介绍了 Options 的概念和使用方法,并对相关接口和类进行了说明和示例。通过使用 Options,我们可以将配置信息从代码中分离出来,提高代码的可维护性和可测试性,同时还能实现配置的热更新和实时响应配置变化。

欢迎进群催更。

asp.net core之Options的更多相关文章

  1. asp.net core选项Options模块的笔记

    这篇博客是写给自己看的.已经不止一次看到AddOptions的出现,不管是在.net core源码还是别人的框架里面,都充斥着AddOptions.于是自己大概研究了下,没有深入,因为,我的功力还是不 ...

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

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 Options绑定 上期我们已经聊过了配置(IConfiguration),今天我们来聊一聊O ...

  3. 5. abp集成asp.net core

    一.前言 参照前篇<4. abp中的asp.net core模块剖析>,首先放张图,这也是asp.net core框架上MVC模块的扩展点 二.abp的mvc对象 AbpAspNetCor ...

  4. ASP.NET Core - 选型系统之选型配置

    1. 选项 前面讲完了.NET Core 下的配置系统,我们可以通过 IConfiguration 服务从各种来源的配置中读取到配置信息,但是每次要用的时候都通过 Iconfiguration 读取配 ...

  5. ASP.NET Core - 选项系统之选项使用

    上一篇 ASP.NET Core - 选项系统之选项配置 中提到 IOptions.IOptionsMonitor 和 IOptionsSnapshot 三个接口,通过这三个接口都可以从依赖注入容器中 ...

  6. ASP.NET Core - 选项系统之选项验证

      就像 Web Api 接口可以对入参进行验证,避免用户传入非法的或者不符合我们预期的参数一样,选项也可以对配置源的内容进行验证,避免配置中的值与选项类中的属性不对应或者不满足预期,毕竟大部分配置都 ...

  7. ASP.NET Core - 选项系统之源码介绍

    .NET Core 选项系统的主要实现在 Microsoft.Extensions.Options 和 Microsoft.Extensions.Options.ConfigurationExtens ...

  8. ASP.NET Core 源码学习之 Options[1]:Configure

    配置的本质就是字符串的键值对,但是对于面向对象语言来说,能使用强类型的配置是何等的爽哉! 目录 ASP.NET Core 配置系统 强类型的 Options Configure 方法 源码解析 ASP ...

  9. ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor

    前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式.而 IOptionsMonitor 则要求配置源必须是 ...

  10. asp.net core轻松入门之MVC中Options读取配置文件

    接上一篇中讲到利用Bind方法读取配置文件 ASP.NET Core轻松入门Bind读取配置文件到C#实例 那么在这篇文章中,我将在上一篇文章的基础上,利用Options方法读取配置文件 首先注册MV ...

随机推荐

  1. Spring Security 报:Encoded password does not look like BCrypt

    SpringBoot 集成 Security 时,报 Encoded password does not look like BCrypt 原因:SecurityConfig 必须 Bean 的形式实 ...

  2. 完美的背景图全屏css代码 – background-size:cover?

    写主题样式的时候经常会碰到用背景图铺满整个背景的需求,这里分享下使用方法 需要的效果 图片以背景的形式铺满整个屏幕,不留空白区域 保持图像的纵横比(图片不变形) 图片居中 不出现滚动条 多浏览器支持 ...

  3. linux安装tomcat,mysql

    环境:centos7.6 ssh连接工具:tabby 安装tomcat 创建目录 mkdir /opt/tomcat 获取tomcat: 1.自己百度下载 2.我这里提供百度网盘 链接:https:/ ...

  4. Axure 手机页面拖动效果

    1.设置好上下固定们,中间放一个动态面板,如下图所示,(刚开始创建是没有图片的) 2.再状态1下再创建一个动态面板 命名为D2,如下图所示 3.在D2的状态1下新建一个宽370(大概手机宽)高1100 ...

  5. 面试精灵:Java后端靠谱、强大的面试题网站(稳拿offer)

    ​面试精灵:一个给力的Java后端面试题网站. 网址:https://offer.skyofit.com 这套题真实.高频.全面.有详细答案.保你稳过面试,让你成为offer收割机.题目包括:Java ...

  6. 2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格, 他可以从北边的任何一个格子出发,到达南边的任何一个格子, 但每一步只能走到东南、正南、西南方向的

    2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格, 他可以从北边的任何一个格子出发,到达南边的任何一个格子, 但每一步只能走到东南.正南.西南方向的 ...

  7. 2022-05-28:某公司计划推出一批投资项目。 product[i] = price 表示第 i 个理财项目的投资金额 price 。 客户在按需投资时,需要遵循以下规则: 客户在首次对项目 pr

    2022-05-28:某公司计划推出一批投资项目. product[i] = price 表示第 i 个理财项目的投资金额 price . 客户在按需投资时,需要遵循以下规则: 客户在首次对项目 pr ...

  8. 2021-10-15:单词拆分。给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。你

    2021-10-15:单词拆分.给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词.说明:拆分时可以重复使用字典中的单词.你 ...

  9. ABP - 模块加载机制

    Abp是一个基于模块化开发的应用程序框架,提供了模块化基础的架构和模块化加载的引擎. 理解模块 一个模块是对一个功能点的封装,可以独立成为一个包,实现了松耦合的代码组织方式.Abp框架的基本思想就是模 ...

  10. IDP 与 DevOps平台:相似之处与关键差异

    软件开发是一个复杂而动态的过程,涉及许多工具.技术和实践.为了更快.更好地交付软件,开发人员需要有效地协作,自动执行任务,并管理环境.然而,由于软件架构的日益复杂,工具和平台的多样性,以及对安全和合规 ...