天天看點

WPF程式中App.Config檔案的讀與寫

原文: WPF程式中App.Config檔案的讀與寫

   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放在這裡,如果需要的話請點選

此處

進行下載下傳。