知行合一|

hiwwwk

园龄:5年1个月粉丝:4关注:12

2022-02-08 23:58阅读: 51评论: 0推荐: 0

16 | 选项数据热更新:让服务感知配置的变化

选项框架关键类型

  • 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>

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;
    }
}

执行程序,输出:image.png
接着手动将配置文件MaxOrderCount的值从10086修改为10010,F5刷新页面
可以看到已经读到了最新的值:image.png
如果我们的服务是单例模式怎么办呢,我们将注册模式从ScopeSingleton,尝试执行会发现启动错误。
image.png
这时,我们将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;
    }
}

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

我们在单例模式下也可以监控配置的变化,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;
    }
}

执行程序之后,手动修改配置文件,输出:image.pngimage.png
这里输出两次是因为现在是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;
        }
    }
}

执行输出:image.png

本文作者:hiwwwk

本文链接:https://www.cnblogs.com/wwwk/p/15873384.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   hiwwwk  阅读(51)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起