.NET C# 配置 Options
使用 options
模式可以带来许多好处,包括清晰的配置管理、类型安全、易于测试和灵活性。但在使用过程中,也需要注意配置复杂性、性能开销和依赖框架等问题。通过合理设计和使用,可以充分发挥 options
模式的优势,提高代码的可维护性和可靠性。
文章目录
环境 .NET6
1 IConfigureOptions
1.1 说明
IConfigureOptions<TOptions>
接口用于配置选项类的实例。通过实现 IConfigureOptions<TOptions>
接口,你可以在应用程序启动时对选项进行额外的配置。
IConfigureOptions<TOptions>
接口定义了一个方法 Configure
,用于配置选项类的实例。其定义如下:
public interface IConfigureOptions<in TOptions> where TOptions : class
{
void Configure(TOptions options);
}
优点 | 说明 |
---|---|
集中配置 | 可以在一个地方集中配置选项,避免在多个地方重复配置。 |
动态配置 | 可以根据运行时条件动态配置选项。 |
分离关注点 | 将配置逻辑与业务逻辑分离,提高代码的可维护性。 |
易于测试 | 可以单独测试配置逻辑,确保配置的正确性。 |
缺点 | |
---|---|
增加复杂性 | 对于简单配置场景,使用 IConfigureOptions<TOptions> 可能会增加额外的复杂性。 |
配置顺序依赖 | 配置的顺序可能会影响最终的配置结果,需要注意配置的执行顺序。 |
1.2 使用
配置类:
public class SettingsBase
{
public override string ToString()
{
return string.Join(Environment.NewLine, this.GetType().GetProperties().Select(p =>
{
if (p.GetValue(this, null) is IList list)
{
return p.Name + " = " + string.Join(", ", list.Cast<object>());
}
return p.Name + " = " + p.GetValue(this, null);
}));
}
}
public class TestSettings : SettingsBase
{
public string StringSetting { get; set; }
public int IntSetting { get; set; }
public bool BoolSetting { get; set; }
public double DoubleSetting { get; set; }
public DateTime DateTimeSetting { get; set; }
public List<string> ListSetting { get; set; }
}
配置器:
public class TestSettingsConfigurator : IConfigureOptions<TestSettings>
{
public void Configure(TestSettings options)
{
options.BoolSetting = true;
options.DateTimeSetting = DateTime.Now;
options.DoubleSetting = 0.123456789;
options.IntSetting = 123456789;
options.ListSetting = new List<string> { "Item1", "Item2", "Item3" };
options.StringSetting = "Test String";
}
}
依赖注入:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 注册配置器
builder.Services.AddSingleton<IConfigureOptions<TestSettings>, TestSettingsConfigurator>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
控制器:
[Route("api/[controller]")]
[ApiController]
public class ConfigsController : ControllerBase
{
private readonly IOptions<TestSettings> _testSettingsOptions;
private readonly ILogger<ConfigsController> _logger;
public ConfigsController(ILogger<ConfigsController> logger, IOptions<TestSettings> testConfigureOptions)
{
_testSettingsOptions = testConfigureOptions;
_logger = logger;
}
[HttpGet("GetConfig")]
public IActionResult GetConfig()
{
return Ok(_testSettingsOptions.Value);
}
}
测试:
2 IOptionsMonitor
2.1 说明
IOptionsMonitor<TOptions>
,用于监控选项更改并提供选项的即时快照。它的主要作用是提供一种方法来在选项值更改时得到通知,并且在应用程序运行时获取当前的选项值。
//
// 摘要:
// 用于在选项实例更改时通知。
//
// 类型参数:
// TOptions:
// 选项类型。
public interface IOptionsMonitor<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] out TOptions>
{
//
// 摘要:
// 使用Microsoft.Extensions.Options.Options.DefaultName返回当前的options实例。
TOptions CurrentValue { get; }
//
// 摘要:
// 返回具有给定名称的配置的TOptions实例。
TOptions Get(string name);
//
// 摘要:
// 注册一个监听器,当命名选项发生变化时调用。
//
// 参数:
// listener:
// 当选项发生变化时调用的操作。
//
// 返回结果:
// 一个可销毁对象,以停止监听变化。
IDisposable OnChange(Action<TOptions, string> listener);
}
IOptionsMonitor<TOptions>
提供以下功能:
- 获取当前值:可以获取选项的当前值。
- 变更通知:当选项值更改时,可以订阅通知。
IOptionsMonitor<TOptions>
应用场景:
- 需要在运行时动态更新配置。
- 需要对配置的变化进行响应。
2.2 使用
控制器:
[HttpGet("GetMonitorConfig")]
public IActionResult GetMonitorConfig()
{
return Ok(_testSettingsMonitor.CurrentValue);
}
测试:
3 IValidateOptions
3.1 说明
IValidateOptions<TOptions>
,用于验证选项值的有效性。通过实现这个接口,你可以确保配置的值符合预期的规则和约束,在应用程序启动时或配置变更时进行验证。IValidateOptions<TOptions>
接口定义了一种方法,用于验证选项实例的值,并返回验证结果。它提供了一种集中管理选项验证逻辑的方式。
public interface IValidateOptions<TOptions> where TOptions : class
{
//
// 摘要:
// 验证指定的命名选项实例(当name为null时,验证全部)。
//
// 参数:
// name:
// 正在验证的选项实例的名称。
//
// options:
// options实例。
//
// 返回结果:
// Microsoft.Extensions.Options.ValidateOptionsResult 结果。
ValidateOptionsResult Validate(string name, TOptions options);
}
3.2 使用
验证器:
public class TestSettingsValidator : IValidateOptions<TestSettings>
{
public ValidateOptionsResult Validate(string? name, TestSettings options)
{
if (string.IsNullOrEmpty(options.StringSetting))
{
return ValidateOptionsResult.Fail("StringSetting cannot be null or empty.");
}
if (options.DoubleSetting >= 1)
{
return ValidateOptionsResult.Fail("DoubleSetting must be greater than 1.");
}
return ValidateOptionsResult.Success;
}
}
依赖注入:
builder.Services.AddSingleton<IValidateOptions<TestSettings>, TestSettingsValidator>();
测试: