Net Core全局配置读取管理方法ConfigurationManager
最近在学习.NetCore的过程中,发现.NetFramework中常用的ConfigurationManager在Core中竟然被干掉了。
也能理解。Core中使用的配置文件全是Json,不像Framework使用的XML,暂时不支持也是能理解的,但是毕竟全局配置文件这种东西还挺重要的,阅读了一些文章后目前有3个解决方案。
一、引入扩展System.Configuration.ConfigurationManager
这个扩展库可以直接在Nuget中获取。
使用方法和说明见.NETCore2.0迁移技巧之web.config配置文件
读取的文件类型和方法都跟.NetFramework中一致,而且仅需引入包就可以,瞬间很兴奋有木有!
但是!在使用过过程中发现这个扩展有问题。项目运行过程中需修改我的app.config文件,对我项目中输出的内容没有丝毫影响,Debug发现获取到的值的确没有变化。重启项目都没有用。只有把项目重新编译才好使。
不知道是不是因为我的打开方式不对,但是最终放弃这个方法。
二、引入扩展Microsoft.Extensions.Options.ConfigurationExtensions
这个扩展库也可以直接在Nuget中获取。
使用方法和说明见ASP.NETCore实现类库项目读取配置文件
这个可以读取application.json中的配置参数,不再使用XML可以说很好的贴近Core的设计理念。
可惜,这个也有点美中不足的地方。首先跟上面的那个一样,运行时修改json文件读取到的内容不会改变,但是至少重启项目可以修改,这个让我欣慰很多。另外就是,这个方法采用的是反序列化的原理,也就是必须有一个跟配置文件对应的实体类才可以,这个感觉比较鸡肋,放弃。
三、自定义扩展方法
这个是我这次说的重点,要是前面两个方法能满足读者你的需求,那么就没有必要看下去。
废话少说,先上代码:
publicclassConfigurationManager { //////配置内容 /// privatestaticNameValueCollection_configurationCollection=newNameValueCollection(); //////配置监听响应链堆栈 /// privatestaticStack>FileListeners=newStack >(); /// ///默认路径 /// privatestaticstring_defaultPath=Directory.GetCurrentDirectory()+"\\appsettings.json"; //////最终配置文件路径 /// privatestaticstring_configPath=null; //////配置节点关键字 /// privatestaticstring_configSection="AppSettings"; //////配置外连接的后缀 /// privatestaticstring_configUrlPostfix="Url"; //////最终修改时间戳 /// privatestaticlong_timeStamp=0L; //////配置外链关键词,例如:AppSettings.Url /// privatestaticstring_configUrlSection{get{return_configSection+"."+_configUrlPostfix;}} staticConfigurationManager() { ConfigFinder(_defaultPath); } //////确定配置文件路径 /// privatestaticvoidConfigFinder(stringPath) { _configPath=Path; JObjectconfig_json=newJObject(); while(config_json!=null) { config_json=null; FileInfoconfig_info=newFileInfo(_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(); elsebreak; } if(config_json==null||config_json[_configSection]==null)return; LoadConfiguration(); } //////读取配置文件内容 /// privatestaticvoidLoadConfiguration() { FileInfoconfig=newFileInfo(_configPath); varconfigColltion=newNameValueCollection(); JObjectconfig_object=LoadJsonFile(_configPath); if(config_object==null||!(config_objectisJObject))return; if(config_object[_configSection]!=null) { foreach(JPropertypropinconfig_object[_configSection]) { configColltion[prop.Name]=prop.Value.ToString(); } } _configurationCollection=configColltion; } //////解析Json文件 /// ///文件路径 /// privatestaticJObjectLoadJsonFile(stringFilePath) { JObjectconfig_object=null; try { StreamReadersr=newStreamReader(FilePath,Encoding.Default); config_object=JObject.Parse(sr.ReadToEnd()); sr.Close(); } catch{} returnconfig_object; } /// ///添加监听树节点 /// ////// privatestaticKeyValuePair CreateListener(FileInfoinfo) { FileSystemWatcherwatcher=newFileSystemWatcher(); 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+=newFileSystemEventHandler(ConfigChangeListener); watcher.EndInit(); returnnewKeyValuePair (info.FullName,watcher); } privatestaticvoidConfigChangeListener(objectsender,FileSystemEventArgse) { longtime=TimeStamp(); lock(FileListeners) { if(time>_timeStamp) { _timeStamp=time; if(e.FullPath!=_configPath||e.FullPath==_defaultPath) { while(FileListeners.Count>0) { varlistener=FileListeners.Pop(); listener.Value.Dispose(); if(listener.Key==e.FullPath)break; } ConfigFinder(e.FullPath); } else { LoadConfiguration(); } } } } privatestaticlongTimeStamp() { return(long)((DateTime.UtcNow-newDateTime(1970,1,1,0,0,0,DateTimeKind.Utc)).TotalMilliseconds*100); } privatestaticstringc_configSection=null; publicstaticstringConfigSection { get{return_configSection;} set{c_configSection=value;} } privatestaticstringc_configUrlPostfix=null; publicstaticstringConfigUrlPostfix { get{return_configUrlPostfix;} set{c_configUrlPostfix=value;} } privatestaticstringc_defaultPath=null; publicstaticstringDefaultPath { get{return_defaultPath;} set{c_defaultPath=value;} } publicstaticNameValueCollectionAppSettings { get{return_configurationCollection;} } /// ///手动刷新配置,修改配置后,请手动调用此方法,以便更新配置参数 /// publicstaticvoidRefreshConfiguration() { 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、外部配置文件
像.NetFramework中一样,可以通过外部配置文件来实现。格式如下
{ "AppSettings.Url":"D:\\test\\app1.json" }
采用格式是“配置节点名.外链后缀”的形式。可以设计多级外部配置文件,只要发现有外部配置节点就会向下寻找,并监听链上的所有节点文件的变化。
但是需要注意的是:一旦存在外部配置节点,此文件中的配置节点和参数将不再参与解析
3、可配置初始化参数
包括默认文件路径在内的多个参数均可以修改,详情见代码。
修改后需要手动调用RefreshConfiguration方法,以使配置内容生效,有点像事务处理。建议在项目的Startup方法中修改配置方法。
4、使用
跟.NetFramework中一样,直接调用ConfigurationManager.Appsettings["Title"]就可以了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。