选项框架关键类型

  • IOptionsMonitor
  • IOptionsSnapshot

场景

  • 范围作用域类型使用IOptionsSnapshot
  • 单例服务使用IOptionsMonitor

通过代码更新选项

  • IPostConfigureOptions

示例

延续使用上一节代码,稍微做些特殊处理
将OrderServce服务从Singleton模式修改为Scope模式
services.AddSingleton<IOrderService, OrderService>() => services.AddScoped<IOrderService, OrderService>()
直接执行程序,输出:image.png
然后我们手动将配置文件MaxOrderCount的值从10086修改为10010,F5刷新页面,发现还是10086,那我们如何读取到新配置呢?
只需要一点简单的改动
OrderService类配置类型从IOptions<OrderServiceOptions>修改为IOptionsSnapshot<OrderServiceOptions>

  1. using Microsoft.Extensions.Options;
  2. namespace OptionsDemo.Services
  3. {
  4. public interface IOrderService { int ShowMaxOrderCount(); }
  5. public class OrderService : IOrderService
  6. {
  7. private readonly IOptionsSnapshot<OrderServiceOptions> _options;
  8. public OrderService(IOptionsSnapshot<OrderServiceOptions> options)
  9. {
  10. _options = options;
  11. }
  12. public int ShowMaxOrderCount()
  13. {
  14. return _options.Value.MaxOrderCount;
  15. }
  16. }
  17. public class OrderServiceOptions
  18. {
  19. public int MaxOrderCount { get; set; } = 200;
  20. }
  21. }

执行程序,输出:image.png
接着手动将配置文件MaxOrderCount的值从10086修改为10010,F5刷新页面
可以看到已经读到了最新的值:image.png
如果我们的服务是单例模式怎么办呢,我们将注册模式从ScopeSingleton,尝试执行会发现启动错误。
image.png
这时,我们将IOptionsSnapshot<OrderServiceOptions>修改为IOptionsMonitor<OrderServiceOptions>
Monitor``与Snapshot的定义略微有些不同,它获取值需要去用CurrentValue字段

  1. using Microsoft.Extensions.Options;
  2. namespace OptionsDemo.Services
  3. {
  4. public interface IOrderService { int ShowMaxOrderCount(); }
  5. public class OrderService : IOrderService
  6. {
  7. private readonly IOptionsMonitor<OrderServiceOptions> _options;
  8. public OrderService(IOptionsMonitor<OrderServiceOptions> options)
  9. {
  10. _options = options;
  11. }
  12. public int ShowMaxOrderCount()
  13. {
  14. return _options.CurrentValue.MaxOrderCount;
  15. }
  16. }
  17. public class OrderServiceOptions
  18. {
  19. public int MaxOrderCount { get; set; } = 200;
  20. }
  21. }

执行输出:image.png,修改之后image.png

我们在单例模式下也可以监控配置的变化,IOptionsMonitor下有一个方法OnChange

  1. using Microsoft.Extensions.Options;
  2. namespace OptionsDemo.Services
  3. {
  4. public interface IOrderService { int ShowMaxOrderCount(); }
  5. public class OrderService : IOrderService
  6. {
  7. private readonly IOptionsMonitor<OrderServiceOptions> _options;
  8. public OrderService(IOptionsMonitor<OrderServiceOptions> options)
  9. {
  10. _options = options;
  11. _options.OnChange(options =>
  12. {
  13. System.Console.WriteLine($"配置发生变化,新值为 :{options.MaxOrderCount}");
  14. });
  15. }
  16. public int ShowMaxOrderCount()
  17. {
  18. return _options.CurrentValue.MaxOrderCount;
  19. }
  20. }
  21. public class OrderServiceOptions
  22. {
  23. public int MaxOrderCount { get; set; } = 200;
  24. }
  25. }

执行程序之后,手动修改配置文件,输出:image.pngimage.png
这里输出两次是因为现在是DeBug模式。

通常情况下,在设计服务的时候,会在ConfigureServices方法这里添加我们的配置注入,还有服务注入,但当我们服务多起来的时候,会形成大量的代码在这,这里建议使用扩展方法的方式,使我们的代码结构更加良好。
Services文件夹添加类OrderServiceExtensions,将其ConfigureServices处代码移动到这里

  1. using Microsoft.Extensions.Configuration;
  2. using OptionsDemo.Services;
  3. namespace Microsoft.Extensions.DependencyInjection
  4. {
  5. public static class OrderServiceExtensions
  6. {
  7. public static IServiceCollection AddOrderService(this IServiceCollection services,IConfiguration configuration)
  8. {
  9. services.Configure<OrderServiceOptions>(configuration);
  10. services.AddSingleton<IOrderService, OrderService>();
  11. return services;
  12. }
  13. }
  14. }

ConfigureServices方法处代码修改为

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddOrderService(Configuration.GetSection("OrderService"));
  4. services.AddControllers();
  5. }

如果我们在设计服务的时候还有一些特殊的需求,比如说我们把配置读取出来以后,还需要再内存里面进行一些特殊的处理,我们就可以使用动态配置的方式
动态配置的方式是再我们Configure的代码之后,调用PostConfigure的方法
例如,这里我们需要把MaxOrderCount加1

  1. using Microsoft.Extensions.Configuration;
  2. using OptionsDemo.Services;
  3. namespace Microsoft.Extensions.DependencyInjection
  4. {
  5. public static class OrderServiceExtensions
  6. {
  7. public static IServiceCollection AddOrderService(this IServiceCollection services,IConfiguration configuration)
  8. {
  9. services.Configure<OrderServiceOptions>(configuration);
  10. services.PostConfigure<OrderServiceOptions>(options =>
  11. {
  12. options.MaxOrderCount += 1;
  13. System.Console.WriteLine(options.MaxOrderCount);
  14. });
  15. services.AddSingleton<IOrderService, OrderService>();
  16. return services;
  17. }
  18. }
  19. }

执行输出:image.png