欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Asp.net core中实现自动更新的Option的方法示例

程序员文章站 2022-07-04 21:48:28
asp.net core可以监视json、xml等配置文件的变化, 自动刷新内存中的配置内容, 但如果想每隔1秒从zookeeper、consul获取最新的配置信息, 需要...

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可以看到返回内容的变化

本文代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。