zoukankan      html  css  js  c++  java
  • [C#] .Net Core 全局配置读取管理方法 ConfigurationManager

      最近在学习.Net Core的过程中,发现.Net Framework中常用的ConfigurationManager在Core中竟然被干掉了。

      也能理解。Core中使用的配置文件全是Json,不像Framework使用的XML,暂时不支持也是能理解的,但是毕竟全局配置文件这种东西还挺重要的,阅读了一些文章后目前有3个解决方案。

    一、引入扩展System.Configuration.ConfigurationManager


      这个扩展库可以直接在Nuget中获取。

      使用方法和说明见 .NET Core 2.0迁移技巧之web.config配置文件

      读取的文件类型和方法都跟.Net Framework中一致,而且仅需引入包就可以,瞬间很兴奋有木有!

      但是!在使用过过程中发现这个扩展有问题。项目运行过程中需修改我的app.config文件,对我项目中输出的内容没有丝毫影响,Debug发现获取到的值的确没有变化。重启项目都没有用。只有把项目重新编译才好使。

      不知道是不是因为我的打开方式不对,但是最终放弃这个方法。

    二、引入扩展Microsoft.Extensions.Options.ConfigurationExtensions

      这个扩展库也可以直接在Nuget中获取。

      使用方法和说明见 ASP.NET Core实现类库项目读取配置文件

      这个可以读取application.json中的配置参数,不再使用XML可以说很好的贴近Core的设计理念。

      可惜,这个也有点美中不足的地方。首先跟上面的那个一样,运行时修改json文件读取到的内容不会改变,但是至少重启项目可以修改,这个让我欣慰很多。另外就是,这个方法采用的是反序列化的原理,也就是必须有一个跟配置文件对应的实体类才可以,这个感觉比较鸡肋,放弃。

    三、自定义扩展方法

      这个是我这次说的重点,要是前面两个方法能满足读者你的需求,那么就没有必要看下去。

      废话少说,先上代码:

      1  public class ConfigurationManager
      2     {
      3         /// <summary>
      4         /// 配置内容
      5         /// </summary>
      6         private static NameValueCollection _configurationCollection = new NameValueCollection();
      7 
      8         /// <summary>
      9         /// 配置监听响应链堆栈
     10         /// </summary>
     11         private static Stack<KeyValuePair<string, FileSystemWatcher>> FileListeners = new Stack<KeyValuePair<string, FileSystemWatcher>>();
     12 
     13         /// <summary>
     14         /// 默认路径
     15         /// </summary>
     16         private static string _defaultPath = Directory.GetCurrentDirectory() + "\appsettings.json";
     17 
     18         /// <summary>
     19         /// 最终配置文件路径
     20         /// </summary>
     21         private static string _configPath = null;
     22 
     23         /// <summary>
     24         /// 配置节点关键字
     25         /// </summary>
     26         private static string _configSection = "AppSettings";
     27 
     28         /// <summary>
     29         /// 配置外连接的后缀
     30         /// </summary>
     31         private static string _configUrlPostfix = "Url";
     32 
     33         /// <summary>
     34         /// 最终修改时间戳
     35         /// </summary>
     36         private static long _timeStamp = 0L;
     37 
     38         /// <summary>
     39         /// 配置外链关键词,例如:AppSettings.Url
     40         /// </summary>
     41         private static string _configUrlSection { get { return _configSection + "." + _configUrlPostfix; } }
     42 
     43 
     44         static ConfigurationManager()
     45         {
     46             ConfigFinder(_defaultPath);
     47         }
     48 
     49         /// <summary>
     50         /// 确定配置文件路径
     51         /// </summary>
     52         private static void ConfigFinder(string Path)
     53         {
     54             _configPath = Path;
     55             JObject config_json = new JObject();
     56             while (config_json != null)
     57             {
     58                 config_json = null;
     59                 FileInfo config_info = new FileInfo(_configPath);
     60                 if (!config_info.Exists) break;
     61 
     62                 FileListeners.Push(CreateListener(config_info));
     63                 config_json = LoadJsonFile(_configPath);
     64                 if (config_json[_configUrlSection] != null)
     65                     _configPath = config_json[_configUrlSection].ToString();
     66                 else break;
     67             }
     68 
     69             if (config_json == null || config_json[_configSection] == null) return;
     70 
     71             LoadConfiguration();
     72         }
     73 
     74         /// <summary>
     75         /// 读取配置文件内容
     76         /// </summary>
     77         private static void LoadConfiguration()
     78         {
     79             FileInfo config = new FileInfo(_configPath);
     80             var configColltion = new NameValueCollection();
     81             JObject config_object = LoadJsonFile(_configPath);
     82             if (config_object == null || !(config_object is JObject)) return;
     83            
     84             if (config_object[_configSection]!=null)
     85             {
     86                 foreach (JProperty prop in config_object[_configSection])
     87                 {
     88                     configColltion[prop.Name] = prop.Value.ToString();
     89                 }
     90             }
     91             
     92             _configurationCollection = configColltion;
     93         }
     94 
     95         /// <summary>
     96         /// 解析Json文件
     97         /// </summary>
     98         /// <param name="FilePath">文件路径</param>
     99         /// <returns></returns>
    100         private static JObject LoadJsonFile(string FilePath)
    101         {
    102             JObject config_object = null;
    103             try
    104             {
    105                 StreamReader sr = new StreamReader(FilePath, Encoding.Default);
    106                 config_object = JObject.Parse(sr.ReadToEnd());
    107                 sr.Close();
    108             }
    109             catch { }
    110             return config_object;
    111         }
    112 
    113         /// <summary>
    114         /// 添加监听树节点
    115         /// </summary>
    116         /// <param name="info"></param>
    117         /// <returns></returns>
    118         private static KeyValuePair<string, FileSystemWatcher> CreateListener(FileInfo info)
    119         {
    120 
    121             FileSystemWatcher watcher = new FileSystemWatcher();
    122             watcher.BeginInit();
    123             watcher.Path = info.DirectoryName;
    124             watcher.Filter = info.Name;
    125             watcher.IncludeSubdirectories = false;
    126             watcher.EnableRaisingEvents = true;
    127             watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Size;
    128             watcher.Changed += new FileSystemEventHandler(ConfigChangeListener);
    129             watcher.EndInit();
    130 
    131             return new KeyValuePair<string, FileSystemWatcher>(info.FullName, watcher);
    132           
    133         }
    134 
    135         private static void ConfigChangeListener(object sender, FileSystemEventArgs e)
    136         {
    137             long time = TimeStamp();
    138             lock (FileListeners)
    139             {
    140                 if (time > _timeStamp)
    141                 {
    142                     _timeStamp = time;
    143                     if (e.FullPath != _configPath || e.FullPath == _defaultPath)
    144                     {
    145                         while (FileListeners.Count > 0)
    146                         {
    147                             var listener = FileListeners.Pop();
    148                             listener.Value.Dispose();
    149                             if (listener.Key == e.FullPath) break;
    150                         }
    151                         ConfigFinder(e.FullPath);
    152                     }
    153                     else
    154                     {
    155                         LoadConfiguration();
    156                     }
    157                 }
    158             }
    159         }
    160 
    161         private static long TimeStamp()
    162         {
    163             return (long)((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds * 100);
    164         }
    165 
    166         private static string c_configSection = null;
    167         public static string ConfigSection
    168         {
    169             get { return _configSection; }
    170             set { c_configSection = value; }
    171         }
    172 
    173 
    174         private static string c_configUrlPostfix = null;
    175         public static string ConfigUrlPostfix
    176         {
    177             get { return _configUrlPostfix; }
    178             set { c_configUrlPostfix = value; }
    179         }
    180 
    181         private static string c_defaultPath = null;
    182         public static string DefaultPath
    183         {
    184             get { return _defaultPath; }
    185             set { c_defaultPath = value; }
    186         }
    187 
    188         public static NameValueCollection AppSettings
    189         {
    190             get { return _configurationCollection; }
    191         }
    192 
    193         /// <summary>
    194         /// 手动刷新配置,修改配置后,请手动调用此方法,以便更新配置参数
    195         /// </summary>
    196         public static void RefreshConfiguration()
    197         {
    198             lock (FileListeners)
    199             {
    200                 //修改配置
    201                 if (c_configSection != null) { _configSection = c_configSection; c_configSection = null; }
    202                 if (c_configUrlPostfix != null) { _configUrlPostfix = c_configUrlPostfix; c_configUrlPostfix = null; }
    203                 if (c_defaultPath != null) { _defaultPath = c_defaultPath; c_defaultPath = null; }
    204                 //释放掉全部监听响应链
    205                 while (FileListeners.Count > 0)
    206                     FileListeners.Pop().Value.Dispose();
    207                 ConfigFinder(_defaultPath);
    208             }
    209         }
    210 
    211     }

      最开始设计的是采用缓存,每次调用比对文件的修改时间,大小等特征,出现变化从新载入配置。后来发现图样图森破!

      C#提供了专门监听文件系统的方法。所以从新设计了监听响应链堆栈来实现。

      

      使用说明:

        1、配置节点:

          可以直接写在项目默认的配置文件appsettings.json中 格式如下

    {
      "AppSettings": {
        "Title": "Test",
        "Version": "1.2.1",
        "AccessToken": "123456@abc.com"
      }
    }
    View Code

          保证配置节点AppSettings存在,剩下的就是以Key-Value的形式来写属性,就可以。

        2、外部配置文件

          像.Net Framework中一样,可以通过外部配置文件来实现。格式如下

    1 {
    2   "AppSettings.Url": "D:\test\app1.json"
    3 }
    View Code

          采用格式是“配置节点名.外链后缀”的形式。可以设计多级外部配置文件,只要发现有外部配置节点就会向下寻找,并监听链上的所有节点文件的变化。

          但是需要注意的是:一旦存在外部配置节点,此文件中的配置节点和参数将不再参与解析

        3、可配置初始化参数

          包括默认文件路径在内的多个参数均可以修改,详情见代码。

          修改后需要手动调用RefreshConfiguration方法,以使配置内容生效,有点像事务处理。建议在项目的Startup方法中修改配置方法。

        4、使用

          跟.Net Framework中一样,直接调用ConfigurationManager.Appsettings["Title"]就可以了。

    以上代码功能完全原创,转载请著名出处。如果有任何问题和疑问欢迎提出,可以给我邮件或者直接留言。

  • 相关阅读:
    Java反射研究(3)
    Java反射研究(2)
    Java反射研究(1)
    从百度文库中复制文本的方法
    jdk/bin中的native2ascii.exe使用
    EA经典入门教程
    JSP自定义标签(3)
    JSP自定义标签(1)
    将Java doc转换为chm的方法
    多态性——vptr和vtable
  • 原文地址:https://www.cnblogs.com/kasimlz/p/7515810.html
Copyright © 2011-2022 走看看