本文将介绍 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
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
通过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
比如:
builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions")); builder.Services.Configure<MyOptions>("Abcd",builder.Configuration.GetSection("MyOptions"));
OptionsBuilder
builder.Services.AddOptions<MyOptions>("OptionsBuilderOptions") .Configure(o => { o.Option1 = "OptionsBuilderOptions"; o.Option2 = 999; }) ;
启动服务DEBUG检验一下,发现我们成功取到值了。
这里需要注意的是IOptions<>是没有Get的方法的,要获取对应名称的Options只能通过IOptionsSnapshot<>或IOptionsMonitor<>。
IValidateOptions
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,我们可以将配置信息从代码中分离出来,提高代码的可维护性和可测试性,同时还能实现配置的热更新和实时响应配置变化。
欢迎进群催更。
