.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文件讀取到的內容不會改變,但是至少重啟項目可以修改,這個讓我欣慰很多。另外就是,這個方法采用的是反序列化的原理,也就是必須有一個跟配置文件對應的實體類才可以,這個感覺比較雞肋,放棄。
三、自定義擴展方法
這個是我這次說的重點,要是前面兩個方法能滿足讀者你的需求,那么就沒有必要看下去。
廢話少說,先上代碼:
public class ConfigurationManager
? ? {
? ? ? ? /// <summary>
? ? ? ? /// 配置內容
? ? ? ? /// </summary>
? ? ? ? private static NameValueCollection _configurationCollection = new NameValueCollection();
? ? ? ? /// <summary>
? ? ? ? /// 配置監聽響應鏈堆棧
? ? ? ? /// </summary>
? ? ? ? private static Stack<KeyValuePair<string, FileSystemWatcher>> FileListeners = new Stack<KeyValuePair<string, FileSystemWatcher>>();
? ? ? ? /// <summary>
? ? ? ? /// 默認路徑
? ? ? ? /// </summary>
? ? ? ? private static string _defaultPath = Directory.GetCurrentDirectory() + "\\appsettings.json";
? ? ? ? /// <summary>
? ? ? ? /// 最終配置文件路徑
? ? ? ? /// </summary>
? ? ? ? private static string _configPath = null;
? ? ? ? /// <summary>
? ? ? ? /// 配置節點關鍵字
? ? ? ? /// </summary>
? ? ? ? private static string _configSection = "AppSettings";
? ? ? ? /// <summary>
? ? ? ? /// 配置外連接的后綴
? ? ? ? /// </summary>
? ? ? ? private static string _configUrlPostfix = "Url";
? ? ? ? /// <summary>
? ? ? ? /// 最終修改時間戳
? ? ? ? /// </summary>
? ? ? ? private static long _timeStamp = 0L;
? ? ? ? /// <summary>
? ? ? ? /// 配置外鏈關鍵詞,例如:AppSettings.Url
? ? ? ? /// </summary>
? ? ? ? private static string _configUrlSection { get { return _configSection + "." + _configUrlPostfix; } }
? ? ? ? static ConfigurationManager()
? ? ? ? {
? ? ? ? ? ? ConfigFinder(_defaultPath);
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 確定配置文件路徑
? ? ? ? /// </summary>
? ? ? ? private static void ConfigFinder(string Path)
? ? ? ? {
? ? ? ? ? ? _configPath = Path;
? ? ? ? ? ? JObject config_json = new JObject();
? ? ? ? ? ? while (config_json != null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? config_json = null;
? ? ? ? ? ? ? ? FileInfo config_info = new FileInfo(_configPath);
? ? ? ? ? ? ? ? if (!config_info.Exists) break;
? ? ? ? ? ? ? ? FileListeners.Push(CreateListener(config_info));
? ? ? ? ? ? ? ? config_json = LoadJsonFile(_configPath);
? ? ? ? ? ? ? ? if (config_json[_configUrlSection] != null)
? ? ? ? ? ? ? ? ? ? _configPath = config_json[_configUrlSection].ToString();
? ? ? ? ? ? ? ? else break;
? ? ? ? ? ? }
? ? ? ? ? ? if (config_json == null || config_json[_configSection] == null) return;
? ? ? ? ? ? LoadConfiguration();
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 讀取配置文件內容
? ? ? ? /// </summary>
? ? ? ? private static void LoadConfiguration()
? ? ? ? {
? ? ? ? ? ? FileInfo config = new FileInfo(_configPath);
? ? ? ? ? ? var configColltion = new NameValueCollection();
? ? ? ? ? ? JObject config_object = LoadJsonFile(_configPath);
? ? ? ? ? ? if (config_object == null || !(config_object is JObject)) return;
? ? ? ? ? ?
? ? ? ? ? ? if (config_object[_configSection]!=null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? foreach (JProperty prop in config_object[_configSection])
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? configColltion[prop.Name] = prop.Value.ToString();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ??
? ? ? ? ? ? _configurationCollection = configColltion;
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 解析Json文件
? ? ? ? /// </summary>
? ? ? ? /// <param name="FilePath">文件路徑</param>
? ? ? ? /// <returns></returns>
? ? ? ? private static JObject LoadJsonFile(string FilePath)
? ? ? ? {
? ? ? ? ? ? JObject config_object = null;
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? StreamReader sr = new StreamReader(FilePath, Encoding.Default);
? ? ? ? ? ? ? ? config_object = JObject.Parse(sr.ReadToEnd());
? ? ? ? ? ? ? ? sr.Close();
? ? ? ? ? ? }
? ? ? ? ? ? catch { }
? ? ? ? ? ? return config_object;
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 添加監聽樹節點
? ? ? ? /// </summary>
? ? ? ? /// <param name="info"></param>
? ? ? ? /// <returns></returns>
? ? ? ? private static KeyValuePair<string, FileSystemWatcher> CreateListener(FileInfo info)
? ? ? ? {
? ? ? ? ? ? FileSystemWatcher watcher = new FileSystemWatcher();
? ? ? ? ? ? watcher.BeginInit();
? ? ? ? ? ? watcher.Path = info.DirectoryName;
? ? ? ? ? ? watcher.Filter = info.Name;
? ? ? ? ? ? watcher.IncludeSubdirectories = false;
? ? ? ? ? ? watcher.EnableRaisingEvents = true;
? ? ? ? ? ? watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Size;
? ? ? ? ? ? watcher.Changed += new FileSystemEventHandler(ConfigChangeListener);
? ? ? ? ? ? watcher.EndInit();
? ? ? ? ? ? return new KeyValuePair<string, FileSystemWatcher>(info.FullName, watcher);
? ? ? ? ??
? ? ? ? }
? ? ? ? private static void ConfigChangeListener(object sender, FileSystemEventArgs e)
? ? ? ? {
? ? ? ? ? ? long time = TimeStamp();
? ? ? ? ? ? lock (FileListeners)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (time > _timeStamp)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? _timeStamp = time;
? ? ? ? ? ? ? ? ? ? if (e.FullPath != _configPath || e.FullPath == _defaultPath)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? while (FileListeners.Count > 0)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? var listener = FileListeners.Pop();
? ? ? ? ? ? ? ? ? ? ? ? ? ? listener.Value.Dispose();
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (listener.Key == e.FullPath) break;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ConfigFinder(e.FullPath);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? LoadConfiguration();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? private static long TimeStamp()
? ? ? ? {
? ? ? ? ? ? return (long)((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds * 100);
? ? ? ? }
? ? ? ? private static string c_configSection = null;
? ? ? ? public static string ConfigSection
? ? ? ? {
? ? ? ? ? ? get { return _configSection; }
? ? ? ? ? ? set { c_configSection = value; }
? ? ? ? }
? ? ? ? private static string c_configUrlPostfix = null;
? ? ? ? public static string ConfigUrlPostfix
? ? ? ? {
? ? ? ? ? ? get { return _configUrlPostfix; }
? ? ? ? ? ? set { c_configUrlPostfix = value; }
? ? ? ? }
? ? ? ? private static string c_defaultPath = null;
? ? ? ? public static string DefaultPath
? ? ? ? {
? ? ? ? ? ? get { return _defaultPath; }
? ? ? ? ? ? set { c_defaultPath = value; }
? ? ? ? }
? ? ? ? public static NameValueCollection AppSettings
? ? ? ? {
? ? ? ? ? ? get { return _configurationCollection; }
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 手動刷新配置,修改配置后,請手動調用此方法,以便更新配置參數
? ? ? ? /// </summary>
? ? ? ? public static void RefreshConfiguration()
? ? ? ? {
? ? ? ? ? ? lock (FileListeners)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //修改配置
? ? ? ? ? ? ? ? if (c_configSection != null) { _configSection = c_configSection; c_configSection = null; }
? ? ? ? ? ? ? ? if (c_configUrlPostfix != null) { _configUrlPostfix = c_configUrlPostfix; c_configUrlPostfix = null; }
? ? ? ? ? ? ? ? if (c_defaultPath != null) { _defaultPath = c_defaultPath; c_defaultPath = null; }
? ? ? ? ? ? ? ? //釋放掉全部監聽響應鏈
? ? ? ? ? ? ? ? while (FileListeners.Count > 0)
? ? ? ? ? ? ? ? ? ? FileListeners.Pop().Value.Dispose();
? ? ? ? ? ? ? ? ConfigFinder(_defaultPath);
? ? ? ? ? ? }
? ? ? ? }
? ? }
最開始設計的是采用緩存,每次調用比對文件的修改時間,大小等特征,出現變化從新載入配置。后來發現圖樣圖森破!
C#提供了專門監聽文件系統的方法。所以從新設計了監聽響應鏈堆棧來實現。
使用說明:
1、配置節點:
可以直接寫在項目默認的配置文件appsettings.json中 格式如下
{
? "AppSettings": {
? ? "Title": "Test",
? ? "Version": "1.2.1",
? ? "AccessToken": "123456@abc.com"
? }
}
保證配置節點AppSettings存在,剩下的就是以Key-Value的形式來寫屬性,就可以。
2、外部配置文件
像.Net Framework中一樣,可以通過外部配置文件來實現。格式如下
{
? "AppSettings.Url": "D:\\test\\app1.json"
}
采用格式是“配置節點名.外鏈后綴”的形式??梢栽O計多級外部配置文件,只要發現有外部配置節點就會向下尋找,并監聽鏈上的所有節點文件的變化。
但是需要注意的是:一旦存在外部配置節點,此文件中的配置節點和參數將不再參與解析
3、可配置初始化參數
包括默認文件路徑在內的多個參數均可以修改,詳情見代碼。
修改后需要手動調用RefreshConfiguration方法,以使配置內容生效,有點像事務處理。建議在項目的Startup方法中修改配置方法。
4、使用
跟.Net Framework中一樣,直接調用ConfigurationManager.Appsettings["Title"]就可以了。
原文地址:http://www.cnblogs.com/kasimlz/p/7515810.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的.Net Core 全局配置读取管理方法 ConfigurationManager的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分布式ID自增算法 Snowflake
- 下一篇: .NET及.NET Core系统架构