选项框架关键类型
- IOptionsMonitor
- IOptionsSnapshot
场景
- 范围作用域类型使用IOptionsSnapshot
- 单例服务使用IOptionsMonitor
通过代码更新选项
- IPostConfigureOptions
示例
延续使用上一节代码,稍微做些特殊处理
将OrderServce服务从Singleton模式修改为Scope模式services.AddSingleton<IOrderService, OrderService>() => services.AddScoped<IOrderService, OrderService>()
直接执行程序,输出:
然后我们手动将配置文件MaxOrderCount的值从10086修改为10010,F5刷新页面,发现还是10086,那我们如何读取到新配置呢?
只需要一点简单的改动
将OrderService类配置类型从IOptions<OrderServiceOptions>修改为IOptionsSnapshot<OrderServiceOptions>
using Microsoft.Extensions.Options;namespace OptionsDemo.Services{public interface IOrderService { int ShowMaxOrderCount(); }public class OrderService : IOrderService{private readonly IOptionsSnapshot<OrderServiceOptions> _options;public OrderService(IOptionsSnapshot<OrderServiceOptions> options){_options = options;}public int ShowMaxOrderCount(){return _options.Value.MaxOrderCount;}}public class OrderServiceOptions{public int MaxOrderCount { get; set; } = 200;}}
执行程序,输出:
接着手动将配置文件MaxOrderCount的值从10086修改为10010,F5刷新页面
可以看到已经读到了最新的值:
如果我们的服务是单例模式怎么办呢,我们将注册模式从Scope为Singleton,尝试执行会发现启动错误。
这时,我们将IOptionsSnapshot<OrderServiceOptions>修改为IOptionsMonitor<OrderServiceOptions>
而Monitor``与Snapshot的定义略微有些不同,它获取值需要去用CurrentValue字段
using Microsoft.Extensions.Options;namespace OptionsDemo.Services{public interface IOrderService { int ShowMaxOrderCount(); }public class OrderService : IOrderService{private readonly IOptionsMonitor<OrderServiceOptions> _options;public OrderService(IOptionsMonitor<OrderServiceOptions> options){_options = options;}public int ShowMaxOrderCount(){return _options.CurrentValue.MaxOrderCount;}}public class OrderServiceOptions{public int MaxOrderCount { get; set; } = 200;}}
执行输出:
,修改之后
我们在单例模式下也可以监控配置的变化,IOptionsMonitor下有一个方法OnChange
using Microsoft.Extensions.Options;namespace OptionsDemo.Services{public interface IOrderService { int ShowMaxOrderCount(); }public class OrderService : IOrderService{private readonly IOptionsMonitor<OrderServiceOptions> _options;public OrderService(IOptionsMonitor<OrderServiceOptions> options){_options = options;_options.OnChange(options =>{System.Console.WriteLine($"配置发生变化,新值为 :{options.MaxOrderCount}");});}public int ShowMaxOrderCount(){return _options.CurrentValue.MaxOrderCount;}}public class OrderServiceOptions{public int MaxOrderCount { get; set; } = 200;}}
执行程序之后,手动修改配置文件,输出:

这里输出两次是因为现在是DeBug模式。
通常情况下,在设计服务的时候,会在ConfigureServices方法这里添加我们的配置注入,还有服务注入,但当我们服务多起来的时候,会形成大量的代码在这,这里建议使用扩展方法的方式,使我们的代码结构更加良好。
在Services文件夹添加类OrderServiceExtensions,将其ConfigureServices处代码移动到这里
using Microsoft.Extensions.Configuration;using OptionsDemo.Services;namespace Microsoft.Extensions.DependencyInjection{public static class OrderServiceExtensions{public static IServiceCollection AddOrderService(this IServiceCollection services,IConfiguration configuration){services.Configure<OrderServiceOptions>(configuration);services.AddSingleton<IOrderService, OrderService>();return services;}}}
ConfigureServices方法处代码修改为
public void ConfigureServices(IServiceCollection services){services.AddOrderService(Configuration.GetSection("OrderService"));services.AddControllers();}
如果我们在设计服务的时候还有一些特殊的需求,比如说我们把配置读取出来以后,还需要再内存里面进行一些特殊的处理,我们就可以使用动态配置的方式
动态配置的方式是再我们Configure的代码之后,调用PostConfigure的方法
例如,这里我们需要把MaxOrderCount加1
using Microsoft.Extensions.Configuration;using OptionsDemo.Services;namespace Microsoft.Extensions.DependencyInjection{public static class OrderServiceExtensions{public static IServiceCollection AddOrderService(this IServiceCollection services,IConfiguration configuration){services.Configure<OrderServiceOptions>(configuration);services.PostConfigure<OrderServiceOptions>(options =>{options.MaxOrderCount += 1;System.Console.WriteLine(options.MaxOrderCount);});services.AddSingleton<IOrderService, OrderService>();return services;}}}
执行输出:
