asp.net core之Options

本文将介绍 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中使用了配置值。
asp.net core之Options
通过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();     } } 

首次请求,可以看到三个内容都是一致的
asp.net core之Options

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

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

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

asp.net core之Options
这里我们可以看到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检验一下,发现我们成功取到值了。
asp.net core之Options

这里需要注意的是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");         } 

启动服务,发出请求,可以发现报错了。
asp.net core之Options

结论

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

欢迎进群催更。
asp.net core之Options

发表评论

评论已关闭。

相关文章