1. 程式人生 > >c#中配置檔案的使用(一)

c#中配置檔案的使用(一)

     在使用log4net的時候,需要自己來配置相關的檔案,之前雖然研究過如何來使用配置檔案,但是時間一久還是有點生疏,下面自己做的一些小test,也讓自己能夠有比較深的印象,在學習過程中,也在網上看到了一位大神寫的相關的內容,比較詳細,這是大神部落格關於配置檔案的地址http://www.cnblogs.com/kissdodog/archive/2013/04/11/3014227.html,然後根據這個我自己做了一些嘗試,並寫出自己的理解和體會。

    在vs中,建立一個專案,然後就會生成一個app.config的配置檔案,可以在這個配置檔案中設定,當然也可以自己寫配置檔案,然後自己去封裝一下,模仿app.config的各項功能實現方法即可,下面的test都是在app.config檔案中實現的。

   1. 直接使用appsettings和connectionStrings節,如果是不太複雜的配置檔案,使用這2個節就夠用了,下面是一個簡單的例子

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="User1" value="password1"/>
    <add key="User2" value="password2"/>
    <add key="User3" value="password3"/>
  </appSettings>
  <connectionStrings>
    <add name ="sqlite" connectionString ="dataSource = /資料庫/db"/>
  </connectionStrings>
    
</configuration>

上面的配置檔案的寫法還是比較好理解的,我需要3個配置項User1,User2,User3,其對應的value分別為password1,password2,password3,在下面的程式碼中,可以很簡單的就能讀取出來上面所寫的配置項。

public void Test1()
        {
            var password1 = ConfigurationManager.AppSettings["User1"];
            var password2 = ConfigurationManager.AppSettings["User2"];
            var password3 = ConfigurationManager.AppSettings["User3"];
            Console.WriteLine(password1 + '\n' + password2 + '\n' + password3 + '\n');
            var connectionString = ConfigurationManager.ConnectionStrings["sqlite"];
            Console.WriteLine(connectionString);
        }

上面的程式執行的程式碼結果,就是顯示了對應的配置項的value,這樣就可以用於在剛開啟程式的時候,對某些變數進行賦值了。

2. 有時會在程式中對配置檔案進行修改,可以按照下面的方法來

static void Main(string[] args)
        {
            Configuration cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); //首先開啟配置檔案
            cfa.AppSettings.Settings.Add("User4", "password4");  //向配置檔案中新增一個新的項
            cfa.AppSettings.Settings["User1"].Value = "password5";//修改配置檔案中的某一個項的value
            cfa.Save();  //儲存配置檔案
            ConfigurationManager.RefreshSection("appSettings");  //重新整理配置檔案
        }
在除錯上面程式碼的時候發現,app.config沒有發生變化,但是在生成的應用程式裡面開啟的時候,發現config檔案是發生 了變化的,之前在查詢相關資訊的時候,網上很多都說這樣修改是不對的,是無法實現的,所以很多就用xml方面的操作方法來進行了修改(這個在後面的學習中會做一個總結)。

但是其實原因在於:在我們除錯的時候,編譯器會把debug下的exe,dll,config給覆蓋掉。執行程式碼時候,其實是將debug目錄下的config內容改變。而專案下的app.config檔案並沒有改變。。。所以再次進行除錯的時候debug下的config又被專案下的app.config覆蓋。

3. vs自帶的handler可以用來自定義一些配置節

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections> <!--這個節其實就是用來設定下面的自定義節的名字和相關的型別-->
    <section name="UserName" type="System.Configuration.NameValueSectionHandler"/>  <!--返回Name Value型別形式的節-->
    <section name="UserAge" type="System.Configuration.DictionarySectionHandler"/> <!--返回字典型別形式的節-->
    <section name="UserHeight" type="System.Configuration.SingleTagSectionHandler"/> <!--基礎結構。處理 .config 檔案中由單個 XML 標記所表示的各配置節。-->
  </configSections>
  
  <UserName>
    <add key="1" value="王二"/>
    <add key="2" value="張三"/>
    <add key="3" value="李四"/>
  </UserName>
  
  <UserAge>
    <add key="1" value="23"/>
    <add key="2" value="24"/>
    <add key="3" value="25"/>
  </UserAge>
  
  <UserHeight one="170" two="180" three="190"/>
  
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
</configuration>  

上面自定了三個節,型別分別為NameValue的表示形式,dictionary的表示形式,還有個是最基礎的結構,類似於appsettings節,寫上相應的配置資訊,然後就可以呼叫了
public static void Test2()
        {
            var section1 = (NameValueCollection)ConfigurationManager.GetSection("UserName");  //首先要獲取對應的配置節
            var name1 = section1["1"];  //這邊也可以使用section1.Allkeys來遍歷,這邊是為了說明如果知道key的值,可以直接獲得對應的Value值
            var name2 = section1["2"];
            var name3 = section1["3"];
            Console.WriteLine(name1 + "," + name2 + "," + name3);

            var section2 = (IDictionary) ConfigurationManager.GetSection("UserAge");
            foreach (var key in section2.Keys)  //這邊因為是字典,因此遍歷是使用keys,跟上面的Allkeys不一樣。
            {
                Console.WriteLine(section2[key]);
            }

            var section3 = (IDictionary) ConfigurationManager.GetSection("UserHeight");
            foreach (var key in section3.Keys)
            {
                Console.WriteLine(section3[key]);
            }
        }

通過上面的例子可以知道,通過系統提供的handler,除了這3個還有很多,我們可以自己來建立一些配置節,並且設定節的屬性,這樣可以更好的把不同功能或者不同型別的配置資訊區分開來。另外根據自己的需要選擇不同的handler,這樣在應用配置檔案的時候也能根據需要更簡單的獲得自己想要的資訊。

4. 如果覺得系統的handler不能滿足自己的要求,這時候可以自定義handler

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="Person" type="Test2.PersonHandler,Test2"/> <!--type後面第一個引數是該節定義的位置,第二個引數是該節所在的程式集-->
  </configSections>
  <Person age="25" name="User1"/>  <!--Person中使用2個hashtable,第一層key是Person,後面的內容是value.第二層key是age和name,值是value-->
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
</configuration>

具體的使用程式碼如下,其實跟使用系統自帶的handler使用方法類似,通俗點說就跟壓縮軟體一樣的就是怎麼壓縮的,使用同樣的方法再解壓縮得到想要的值就可以了
class Program
    {
        static void Main(string[] args)
        {
            Hashtable section = ConfigurationManager.GetSection("Person") as Hashtable; //跟上面一樣獲取section,不過這個section是hashtable型別的。
            if (section != null)
                foreach (DictionaryEntry key in section)      //第一層table
                {
                    Hashtable attrs = (Hashtable) key.Value; //根據key,來獲取對應的value,而這個value又是第2層hashtable
                    foreach (DictionaryEntry attr in attrs)
                    {
                        Console.WriteLine(attr.Key);    //解析第2層hashtable就可以得到配置檔案中Person節中的資訊了。
                        Console.WriteLine(attr.Value);
                    }
                }
        }
    }

    class PersonHandler : IConfigurationSectionHandler
    {
        public object Create(object parent, object configContext, XmlNode section)
        {
            Hashtable configSection = new Hashtable();
            Hashtable configAttribute = new Hashtable();
            if (section.Attributes != null)
            {
                foreach (XmlAttribute attribute in section.Attributes)
                {
                    if (attribute.NodeType == XmlNodeType.Attribute)
                    {
                        configAttribute.Add(attribute.Name, attribute.Value);
                    }
                }
            }
            configSection.Add(section.Name, configAttribute);
            return configSection;    
        }
    }