.Net 配置绑定 IOptions

准备

  首先准备下appsettins.json以及目标类

 appsettins.json

"StudentSettings": {
    "Id": 1023,
    "Name": "Development"
  }

 

  创建实体类

public class StudentSettings
{
    public int Id { get; set; }

    public string Name { get; set; }
}

 

 

绑定

//方式1
Configuration.GetSection(nameof(StudentSettings)).Bind(new StudentSettings());
//方式2
Configuration.GetSection(nameof(StudentSettings)).Get<StudentSettings>();
//方式3
  services.Configure<StudentSettings>(Configuration.GetSection(nameof(StudentSettings)));

 

 

获取配置

  使用IOptions接收注入的Options类,即可获取配置

public class TestController
{
    private readonly IOptionsMonitor<StudentSettings> _studentSettings;

    public TestController(IOptionsMonitor<StudentSettings> studentSettings)
    {
        _studentSettings = studentSettings;
    }

    [HttpGet("~/test")]
    public async Task<IActionResult> Test()
    {
        Console.WriteLine(_studentSettings.CurrentValue.Id);
        await Task.Delay(5000);
        Console.WriteLine(_studentSettings.CurrentValue.Name);

        return Ok();
    }
}

 

 

配置操作类接口

IOptions<TOptions>

  • 注册的实例为单例,可以注入到任何服务生存期;
  • 不支持在应用启动后读取配置数据,既修改配置后不会自动更新到已启动的程序;

IOptionsSnapshot<IOptions>

  • 注册为Scope,无法注入到单例;
  • 由于注册为Scope,每次请求重新加载配置,配置修改后下个请求就能更新配置项;

IOptiionsMonitor<IOptions>

  • 注册为单例,可以注入到任何服务生存期;

  • 配置修改可以会重新加载配置,获取新值

 

 

Test

查看代码
private readonly IOptionsMonitor<StudentSettings> _studentSettings;
//private readonly StudentSettings _studentSettings1;
public WeatherForecastController(ILogger<WeatherForecastController> logger,
                                 IOptionsMonitor<StudentSettings> studentSettings, 
                                 //IOptionsSnapshot<StudentSettings> studentSettings,
                                 //IOptionsSnapshot<StudentSettings> studentSettings,
                                 )
{
  _logger = logger;
  _studentSettings = studentSettings;
  //_studentSettings1 = studentSettings.Val;
}

[HttpGet("~/test")]
public async Task<IActionResult> Test()
{
    Console.WriteLine(_studentSettings.CurrentValue.Id);
    //Console.WriteLine(_studentSettings1.Id);
    await Task.Delay(5000);//留下时间修改appsetting.json配置
    Console.WriteLine(_studentSettings.CurrentValue.Name);//IOptionsMonitor配置发生更改时就可以获取新值,如果在构造函数就获取Val则获取不到新值
    //Console.WriteLine(_studentSettings1.Name);
    return Ok();
}

  在delay的时候如果使用的是IOptiionsMonitor,配置一改就会更新StudentSettings

  如果使用的是IOptionsSnapshot,StudentSettings在当前请求都不会变,直到下个请求

  IOptions在程序启动时是什么值就一直是什么值,直到项目重启

 

 

 IOptionsMonitor源码

  OptionsMonitor注册为单例却能实时更新是由于IOptionsChangeTokenSource<TOptions>,它引用了代表配置文件的对象config,所以配置文件更新会被ConfigurationChangeTokenSource监听到,IOptionsMonitor就会跟着更新;

public OptionsMonitor(IOptionsFactory<TOptions> factory, IEnumerable<IOptionsChangeTokenSource<TOptions>> sources, IOptionsMonitorCache<TOptions> cache)
{
    _factory = factory;
    _sources = sources;
    _cache = cache;

    foreach (var source in _sources)
    {
        var registration = ChangeToken.OnChange(
                () => source.GetChangeToken(),
                (name) => InvokeChanged(name),
                source.Name);

        _registrations.Add(registration);
    }
}

//Microsoft.Extensions.Options.ConfigurationExtensions.dll

public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config, Action<BinderOptions> configureBinder)
    where TOptions : class
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }

    if (config == null)
    {
        throw new ArgumentNullException(nameof(config));
    }

    services.AddOptions();
    services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, config));
    return services.AddSingleton<IConfigureOptions<TOptions>>(new NamedConfigureFromConfigurationOptions<TOptions>(name, config, configureBinder));
}

 

posted @ 2022-12-05 14:43  贰拾~  阅读(178)  评论(0编辑  收藏  举报