最近在學習.Net Core的過程當中,發現.Net Framework中經常使用的ConfigurationManager在Core中居然被幹掉了。html
也能理解。Core中使用的配置文件全是Json,不像Framework使用的XML,暫時不支持也是能理解的,可是畢竟全局配置文件這種東西還挺重要的,閱讀了一些文章後目前有3個解決方案。web
這個擴展庫能夠直接在Nuget中獲取。json
使用方法和說明見 .NET Core 2.0遷移技巧之web.config配置文件緩存
讀取的文件類型和方法都跟.Net Framework中一致,並且僅需引入包就能夠,瞬間很興奮有木有!app
可是!在使用過過程當中發現這個擴展有問題。項目運行過程當中需修改個人app.config文件,對我項目中輸出的內容沒有絲毫影響,Debug發現獲取到的值的確沒有變化。重啓項目都沒有用。只有把項目從新編譯纔好使。ide
不知道是否是由於個人打開方式不對,可是最終放棄這個方法。post
這個擴展庫也能夠直接在Nuget中獲取。學習
使用方法和說明見 ASP.NET Core實現類庫項目讀取配置文件url
這個能夠讀取application.json中的配置參數,再也不使用XML能夠說很好的貼近Core的設計理念。spa
惋惜,這個也有點美中不足的地方。首先跟上面的那個同樣,運行時修改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#提供了專門監聽文件系統的方法。因此重新設計了監聽響應鏈堆棧來實現。
使用說明:
一、配置節點:
能夠直接寫在項目默認的配置文件appsettings.json中 格式以下
{ "AppSettings": { "Title": "Test", "Version": "1.2.1", "AccessToken": "123456@abc.com" } }
保證配置節點AppSettings存在,剩下的就是以Key-Value的形式來寫屬性,就能夠。
二、外部配置文件
像.Net Framework中同樣,能夠經過外部配置文件來實現。格式以下
1 { 2 "AppSettings.Url": "D:\\test\\app1.json" 3 }
採用格式是「配置節點名.外鏈後綴」的形式。能夠設計多級外部配置文件,只要發現有外部配置節點就會向下尋找,並監聽鏈上的全部節點文件的變化。
可是須要注意的是:一旦存在外部配置節點,此文件中的配置節點和參數將再也不參與解析
三、可配置初始化參數
包括默認文件路徑在內的多個參數都可以修改,詳情見代碼。
修改後須要手動調用RefreshConfiguration方法,以使配置內容生效,有點像事務處理。建議在項目的Startup方法中修改配置方法。
四、使用
跟.Net Framework中同樣,直接調用ConfigurationManager.Appsettings["Title"]就能夠了。
以上代碼功能徹底原創,轉載請著名出處。若是有任何問題和疑問歡迎提出,能夠給我郵件或者直接留言。