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;
}
///
///添加监听树节点
///
///
///
privatestaticKeyValuePairCreateListener(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"]就可以了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。