net core获取appsetting.json的另外一种思路(全局,实时变化无需重启项目)

最近在写net core的项目,在非controller和service里面需要用到appsetting.json文件里面的一些配置,查资料大概有几种思路:

  • 注入,然后config.GetSection("xxx")
  • 写一个监听,filewatch,去监听appsetting.json的变化,读取key-value。
  • 工具类里面传入再走一遍 new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile($"appsettings.json", optional: true, reloadOnChange: true)
  • 使用IOptions<TOptions>,创建对应的实体类

我在查资料的时候发现了一个IOptionsMonitor<T>,这个可以监听到文件的变化,结合IOptionsMonitor<T>,我写了一个工具类,具体使用办法如下:

(1)创建appsetting.json对应的实体类文件,属性的名字要与配置文件里面的一一对应。

 1 public class AllSetting
 2 {
 3         ///// <summary>
 4         ///// 数据库配置
 5         ///// </summary>
 6         public ConnectionSetting ConnectionStrings { get; set; }
 7 
 8         ///// <summary>
 9         ///// 日志模块
10         ///// </summary>
11         public LoggingSetting Logging { get; set; }
12 
13         ///// <summary>
14         ///// AllowedHosts 
15         ///// </summary>
16         public string AllowedHosts { get; set; }
17 }
 1 {
 2     "ConnectionStrings": {
 3         "DefaultConnection": "xxxx"
 4         //"PgSqlConnection": "xxxx",
 5         //"MySqlConnection": "xxxx",
 6         //"OracleConnection": "xxxx"
 7     },
 8     "Logging": {
 9         "LogLevel": {
10             "Default": "Warning"
11         }
12     },
13     "AllowedHosts": "*",
14     "Gateway": {
15         "Uri": "xxxx"
16     }
17 }

(2) 编写工具类AppsettingsUtility

  1  /// <summary>
  2     /// 全局获取app的设置工具类
  3     /// </summary>
  4     public class AppsettingsUtility
  5     {
  6         /// <summary>
  7         /// log4net
  8         /// </summary>
  9         private readonly ILog log;
 10 
 11         /// <summary>
 12         /// serviceProvider
 13         /// </summary>
 14         private static ServiceProvider serviceProvider;
 15 
 16         /// <summary>
 17         /// _services
 18         /// </summary>
 19         private static IServiceCollection _services;
 20 
 21         /// <summary>
 22         /// _configuration
 23         /// </summary>
 24         private static IConfiguration _configuration;
 25 
 26         /// <summary>
 27         /// 初始化工具类
 28         /// </summary>
 29         /// <param name="provider"></param>
 30         public AppsettingsUtility(IServiceCollection services, IConfiguration configuration)
 31         {
 32             _services = services;
 33             _configuration = configuration;
 34             // 仓库名 统一的
 35             log = LogManager.GetLogger("仓库名", typeof(AppsettingsUtility));
 36             if (_services == null || _configuration == null)
 37             {
 38                 log.Error("初始化配置工具类发生异常:_services或_configuration为空");
 39                 throw new NullReferenceException("初始化配置工具类发生异常");
 40             }
 41             try
 42             {
 43                 serviceProvider = _services.BuildServiceProvider();
 44             }
 45             catch (Exception ex)
 46             {
 47                 log.Error("_services.BuildServiceProvider()失败:" + ex.ToString());
 48             }
 49         }
 50 
 51         /// <summary>
 52         /// 获取IOptionsMonitor<T>
 53         /// </summary>
 54         /// <typeparam name="T">泛型</typeparam>
 55         /// <returns>IOptionsMonitor<T></returns>
 56         public static IOptionsMonitor<T> GetMonitor<T>()
 57         {
 58             if (serviceProvider == null)
 59             {
 60                 throw new NullReferenceException("获取失败,ServiceProvider为空");
 61             }
 62             if (typeof(T) != typeof(AllSetting))
 63             {
 64                 // TODO: 要限定传递的参数值或者每个setting都注册一遍
 65             }
 66             return serviceProvider.GetRequiredService<IOptionsMonitor<T>>();
 67         }
 68 
 69         /// <summary>
 70         /// 获取单个的设置实体
 71         /// </summary>
 72         /// <typeparam name="T">泛型</typeparam>
 73         /// <returns>T</returns>
 74         public static T GetSettingsModel<T>()
 75         {
 76             if (serviceProvider == null)
 77             {
 78                 throw new NullReferenceException("获取失败,ServiceProvider为空");
 79             }
 80             if (typeof(T) != typeof(AllSetting))
 81             {
 82                 // TODO: 要限定传递的参数值或者每个setting都注册一遍
 83             }
 84             return serviceProvider.GetRequiredService<IOptionsMonitor<T>>().CurrentValue;
 85         }
 86 
 87         /// <summary>
 88         /// 通过key获取设置
 89         /// </summary>
 91         /// <param name="key">key</param>
 92         /// <returns>设置内容</returns>
 93         public static string GetSetting(string key)
 94         {
 95             if (_configuration == null)
 96             {
 97                 throw new NullReferenceException("获取失败,IConfiguration为空");
 98             }
 99             if (string.IsNullOrEmpty(key))
100             {
101                 throw new NullReferenceException("获取失败,key不能为空");
102             }
103             return _configuration.GetSection(key).Value;
104         }
105     }

(3)在Startup中注册

1  // 注入设置类到管道中
2 services.AddOptions();
3 services.Configure<AllSetting>(Configuration);
4 // 初始化工具类
5 new AppsettingsUtility(services,Configuration);

(4)使用

1 var aa = AppsettingsUtility.GetMonitor<AllSetting>().CurrentValue;
2 var bb = AppsettingsUtility.GetSettingsModel<JwtSetting>();
3 var bb = AppsettingsUtility.GetSetting("Appsetting:xxx");

如果把配置文件改变了,再调用获取设置的时候,设置的值会更新,项目不用重启。这样做对性能的影响没有测试。

如果我这边的思路有什么错误的话,还望批评指出。

原文地址:https://www.cnblogs.com/CoderSilence/p/11842338.html