WPF程序中的App.Config文件是我們應用程序中經常使用的一種配置文件,System.Configuration.dll文件中提供了大量的讀寫的配置,所以它是一種高效的程序配置方式,那么今天我就這個部分來做一次系統性的總結。
App.Config文件是系統默認的應用程序配置文件,在我們使用后進行編譯時會生成“程序集名稱+.exe.config”文件,其本質上也是一個XML文件,在我們的應用程序中添加應用程序配置文件后,默認生成下面的內容。
<?xml version="1.0" encoding="utf-8" ?> <configuration> </configuration>
后面可以根據需要添加我們想要配置的內容,例如我們想要自定義一個section,那么我們首先需要增加一個configSections節點,然后再添加section子節點,在子節點中我們需要添加名稱name 類型type等節點信息,具體配置信息如下:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="eas" type="EAS.ConfigHandler,EAS.MicroKernel"/> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/> </configSections> <eas> <objects> <object name="MessageBus" assembly="EAS.MicroKernel" type="EAS.Sockets.Bus.SocketBus" LifestyleType="Singleton"> <property name="Url" type="string" value="socket.tcp://127.0.0.1:1000/"/> </object> </objects> </eas> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/> <providers> <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"></provider> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/> </providers> </entityFramework> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/> </startup> <appSettings> <add key="AspNetAddress" value="http://192.168.3.199:8088"/> <add key="ServerDog" value="192.168.3.199:8001"/> <add key="DICSCtrl" value="192.168.3.100:4503"/> <add key="BGServerDeamon" value="192.168.3.199:5915"/> <add key="MySQLServer" value="localhost"/> <add key="DataSimulator" value="DataRinse"/> <!--當前軟件部署的時間--> <add key="DeploymentTime" value="20170822"/> <add key="UnitWidth" value="1920"/> <!--單個屏幕高--> <add key="UnitHeight" value="1080"/> <!--橫向屏幕數量--> <add key="HorizontalCount" value="2"/> <!--豎向屏幕數量--> <add key="VerticalCount" value="2"/> </appSettings> </configuration>
這其中最常用的就是appSettings節點了,通過添加key和value能夠快速添加鍵值對,從而完成參數的配置與讀寫操作。
第一部分:基礎篇
這一部分主要介紹最常用的操作,那就是讀取操作了。
string sqlServer= System.Configuration.ConfigurationSettings.AppSettings["MySQLServer"];
通過輸入唯一的key就可以來查找當前key對應的value值的內容了。
后面就是為App.Config文件來寫入值了,我們首先來看如何為其中的某一個節點寫入值的操作。
1 將當前應用程序的配置文件作為 System.Configuration.Configuration 對象打開。
System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None);
上面打開特定的exe.config文件的形式和下面的類似,都可以打開exe.config文件的內容,只不過下面這種方式更為靈活。
ExeConfigurationFileMap map = new ExeConfigurationFileMap(); Assembly assembly = Assembly.GetCallingAssembly(); Uri uri = new Uri(Path.GetDirectoryName(assembly.CodeBase)); map.ExeConfigFilename = Path.Combine(uri.LocalPath, assembly.GetName().Name + ".exe.config"); System.Configuration.Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(map, 0); string sqlServer = configuration.AppSettings.Settings["MySQLServer"].Value;
2 讀取和寫入特定的項
//讀取 string sqlServer = config.AppSettings.Settings["MySQLServer"].Value; //寫入 config.AppSettings.Settings["MySQLServer"].Value = "XXX"; //增加節點 config.AppSettings.Settings.Add("MySQLServer","XXX");
3 寫入后要進行保存,並刷新
config.Save(System.Configuration.ConfigurationSaveMode.Modified); System.Configuration.ConfigurationManager.RefreshSection("appSettings");
這樣我們就完成了整個讀取和寫入的操作了,基礎的操作部分也就包含這么多的部分,通過這些操作能夠對常規的一些操作進行處理,並完成軟件的一些基礎的要求。
第二部分:提高篇
這個部分我們來將一些稍微復雜一點的操作,對於appsettings中的操作,我們當然可以非常輕松的通過這些操作來完成配置,但是如果是自定義的section節點中的特定值那么我們應該怎樣來進行讀寫操作呢?我們想其實app.config文件本質上也是一個xml文件,其實我們完全可以按照常規的xml操作的方式來進行讀寫操作,下面的代碼以讀取自定義節點中的xml文件為例來進行說明。
private void DoSaveConfig() { try { var section = config.GetSection("eas"); var sontSection = section.CurrentConfiguration.GetSection("objects"); string filePath = section.CurrentConfiguration.FilePath; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(filePath); #region 保存EAS部分 XmlNode easNode = ((System.Xml.XmlElement)(xmlDoc.SelectSingleNode("configuration/eas/objects/object/property"))); string currentValue = easNode.Attributes["value"].Value; string[] infos = currentValue.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (infos.Length == 2) { string info = infos[1]; string[] ipport = info.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries); string oldIp = ipport[0]; string oldPort = ipport[1]; StringBuilder sb = new StringBuilder(); sb.Append("socket.tcp://").Append(ServerIp).Append(":").Append(oldPort).Append("/"); easNode.Attributes["value"].Value = sb.ToString(); } #endregion XmlNode appSettingsNode = xmlDoc.SelectSingleNode("configuration/appSettings"); foreach (XmlNode childNode in appSettingsNode.ChildNodes) { if (childNode.NodeType == XmlNodeType.Element) { switch (childNode.Attributes["key"].Value) { case "AspNetAddress": StringBuilder web = new StringBuilder(); childNode.Attributes["value"].Value = web.Append("http://").Append(ServerIp).Append(":").Append(WebPort).ToString(); break; case "ServerDog": StringBuilder serverDog = new StringBuilder(); childNode.Attributes["value"].Value = serverDog.Append(ServerIp).Append(":").Append(ServerDogPort).ToString(); break; case "DICSCtrl": StringBuilder processor = new StringBuilder(); childNode.Attributes["value"].Value = processor.Append(ProcessorIp).Append(":").Append(ProcessorPort).ToString(); break; case "BGServerDeamon": StringBuilder bgserverdeamon = new StringBuilder(); childNode.Attributes["value"].Value = bgserverdeamon.Append(ServerIp).Append(":").Append(BGServerDeamonPort).ToString(); break; case "MySQLServer": childNode.Attributes["value"].Value = ServerIp; break; case "DeploymentTime": DeployTime = DateTime.Now.ToString("yyyy-MM-dd"); childNode.Attributes["value"].Value = DeployTime; break; case "UnitWidth": childNode.Attributes["value"].Value = UnitWidth.ToString(); break; case "UnitHeight": childNode.Attributes["value"].Value = UnitHeight.ToString(); break; case "HorizontalCount": childNode.Attributes["value"].Value = HCount.ToString(); break; case "VerticalCount": childNode.Attributes["value"].Value = VCount.ToString(); break; case "CurrentVersion": childNode.Attributes["value"].Value = CurrentVersion; break; case "PartialGISAddress": childNode.Attributes["value"].Value = GISPath; break; case "MediaShareFolder": childNode.Attributes["value"].Value = DiskMapPath; break; case "MediaSharedRemoteFolder": StringBuilder mediasharedfolder = new StringBuilder(); childNode.Attributes["value"].Value = mediasharedfolder.Append(@"\\").Append(ServerIp).Append(@"\SharedResources").ToString(); break; case "DynamicHTMLsPath": childNode.Attributes["value"].Value = HTMLPath; break; default: break; } } } xmlDoc.Save(filePath); MessageBox.Show("配置文件參數保存成功,重啟軟件后生效!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { ; } }
這其中 config為第一部分中打開的System.Configuration.Configuration 對象,后面的部分就是一些常規的XML文件的一些操作,首先是Load然后再配置節點信息,這里配置節點的時候需要注意的是當前XmlNodeType,這個是必須要進行確認的,只有當前的XMLNodeType為Element的項才能夠進行key和value的值的讀寫,其它的都是一些常規的操作,具體內容請參考下面的DEMO中的部分代碼。
在上面的代碼中,加載xml文件到XmlDocument中除了采用xmlDoc.Load("具體路徑")的方式之外,還可以采用下面的方式來進行,這里我們需要去比較兩種方式的優劣。
string xml = ((System.Xml.XmlElement)(System.Configuration.ConfigurationManager.GetSection("eas"))).InnerXml; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xml);
第三部分:擴展篇
為什么要自定義的配置節點?
確實,有很多人在使用config文件都是直接使用appSetting的,把所有的配置參數全都塞到那里,這樣做雖然不錯, 但是如果參數過多,這種做法的缺點也會明顯地暴露出來:appSetting中的配置參數項只能按key名來訪問,不能支持復雜的層次節點也不支持強類型, 而且由於全都只使用這一個集合,你會發現:完全不相干的參數也要放在一起!
想擺脫這種困擾嗎?自定義的配置節點將是解決這個問題的一種可行方法。
關於這方面的具體描述,請參考這里,並從當前位置下載DEMO查看具體的實例。
最后將整個部分的測試用的DEMO放在這里,如果需要的話請點擊此處進行下載。