视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Asp.net core中实现自动更新的Option的方法示例
2020-11-27 22:34:39 责编:小采
文档

Asp.net core可以监视json、xml等配置文件的变化, 自动刷新内存中的配置内容, 但如果想每隔1秒从zookeeper、consul获取最新的配置信息, 需要自己实现.

阅读了 Asp.net core Document的Custom configuration provider, 得知只需要实现自己的IConfigurationSource和对应ConfigurationProvider即可

在这个示例中, 我建立了一个简单的option, 只包含一个不断变化的计数器变量.

public class RefreshableOptions
{
 public int IncreasementCount { get; set; }
}

实现IConfigurationSource和对应ConfigurationProvider, 内部有一个timer模拟从外部获取了最新的数据, 这里为简单起见, 采用硬编码的方式指定了option的路径

public class AutoRefreshConfigurationSource : IConfigurationSource
{
 public IConfigurationProvider Build(IConfigurationBuilder builder)
 {
 return new AutoRefreshConfigurationProvider();
 }
}

public class AutoRefreshConfigurationProvider : ConfigurationProvider
{
 private int count = 0;
 private bool isChanged;

 public AutoRefreshConfigurationProvider() : base()
 {
 Timer timer = new Timer(TimerCallback);
 timer.Change(1000, 3000);
 }

 public override void Load()
 {
 var beforeData = Data;
 // 这里采用硬编码指定option的路径
 Data = new Dictionary<string, string>() { { "AutoRefreshOptions:IncreasementCount", count.ToString() } };
 isChanged = IsDictionaryChanged(beforeData, Data);
 }

 private void TimerCallback(object state)
 {
 count++;
 this.Load();
 if (isChanged)
 {
 base.OnReload();//通知IConfiguration实例, 有参数发生了改变
 isChanged = false;
 }
 }
 //判断两个Idictionary是否有不同的帮助方法
 private static bool IsDictionaryChanged(IDictionary<string, string> before, IDictionary<string, string> after)
 {
 if (before == null && after == null)
 {
 return false;
 }
 if ((before == null) != (after == null))
 {
 return true;
 }
 if (before.Count != after.Count)
 {
 return true;
 }
 var ignoreCaseBefore = new Dictionary<string, string>(before, StringComparer.OrdinalIgnoreCase);
 foreach (var afterItemKey in after.Keys)
 {
 if (!ignoreCaseBefore.TryGetValue(afterItemKey, out var beforeItemValue))
 {
 return true;
 }
 if (beforeItemValue != after[afterItemKey])
 {
 return true;
 }
 ignoreCaseBefore.Remove(afterItemKey);
 }
 if (ignoreCaseBefore.Count > 0)
 {
 return true;
 }
 return false;
 }
}

实现扩展方法

public static class AutoRereshConfigurationExtensions
{
 public static IConfigurationBuilder AddAutoRereshConfiguration(this IConfigurationBuilder builder)
 {
 return builder.Add(new AutoRefreshConfigurationSource());
 }
}

使用方法

新建一个WebApi项目, 在Program.CreateWebHostBuilder中增加黄色部分

WebHost.CreateDefaultBuilder(args)
 .ConfigureAppConfiguration(config =>
 {
 config.AddAutoRereshConfiguration();
 })
 .UseStartup<Startup>();

在Startup. ConfigureServices中配置

services.Configure<RefreshableOptions>(Configuration.GetSection("AutoRefreshOptions"));

修改ValuesController

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
 private RefreshableOptions refreshableOptions;
 public ValuesController(IOptionsSnapshot<RefreshableOptions> refreshableOptions)
 {
 this.refreshableOptions = refreshableOptions.Value;
 }

 [HttpGet]
 public ActionResult<IEnumerable<string>> Get()
 {
 return new string[] { "value1", "value2", refreshableOptions.IncreasementCount.ToString() };
 }
}

启动后不停的刷新http://localhost:5000/api/values可以看到返回内容的变化

本文代码

下载本文
显示全文
专题