1. 程式人生 > >配置文件的讀寫

配置文件的讀寫

copy ssd 服務器 主程 tostring 當前 opera enc top

System.ConfigurationManager類用於對配置文件的讀取。其具有的成員如下:

一、AppSettings

  AppSetting是最簡單的配置節,讀寫非常簡單。

名稱 說明
AppSettings 獲取當前應用程序默認配置的 AppSettingsSection 數據
ConnectionStrings 獲取當前應用程序默認配置的 ConnectionStringsSection 數據

技術分享
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="DB" value="Access" />
  </appSettings>
  <connectionStrings>
    <add name="connstr" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\C#Code\DBOperation\ykjj.mdb"/>
  </connectionStrings>
</configuration>
技術分享

  示例:

技術分享
    class Program
    {
        static void Main(string[] args)
        {
            string strAppSettings = System.Configuration.ConfigurationManager.AppSettings["DB"];  //通過屬性索引獲取值
            Console.WriteLine(strAppSettings);

            string strConnection = System.Configuration.ConfigurationManager.ConnectionStrings["connstr"].ToString();
            Console.WriteLine(strConnection);

            Console.ReadKey();
        }
    }
技術分享

  技術分享

  對於以上這一個appSettings與connectionStrings都是由ConfigurationManager提供的兩個屬性來讀取的。通常大多數的配置信息都可以放在appSettings裏。但是如果你覺得不夠用了,你還可以使用自定義配置信息。

二、自定義配置節

  1、自帶Handler

  關於自定義配置節,Configuration提供了很多Handler類來供你選擇使用。甚至如果你覺得不夠,還可以自定義處理Handler。
  先來學下使用怎麽使用三個簡單的Handler:

  • System.Configuration.NameValueSectionHandler
  • System.Configuration.DictionarySectionHandler
  • System.Configuration.SingleTagSectionHandler

  配置文件代碼示例:

技術分享
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="Person" type="System.Configuration.NameValueSectionHandler"/> <!--以NameValue鍵值/對的形式返回配置節中的信息-->
    <section name="Man" type="System.Configuration.DictionarySectionHandler"/>  <!--以Dictionary字典鍵值對的形式返回配置節中的信息-->
    <section name="Name" type="System.Configuration.SingleTagSectionHandler" /> <!--基礎結構。處理 .config 文件中由單個 XML 標記所表示的各配置節。-->
  </configSections>
  <Person>
    <add key="老大" value="劉備" />
    <add key="老二" value="關羽" />
    <add key="老三" value="張飛" />
  </Person>

  <Man>
    <add key="老大" value="曹操" />
    <add key="老二" value="典韋" />
    <add key="老三" value="郭嘉" />
  </Man>
  
  <Name one="1" two="2" three="3" four="4" five="5" /> <!--註意是要單個節SingleTagSectionHandler才能處理,但是無論你索性有多少個也能處理-->
</configuration>
技術分享

  讀取代碼示例:

技術分享
static void Main(string[] args)
{
    //讀取人名
    NameValueCollection nvc = (NameValueCollection)ConfigurationManager.GetSection("Person");
    foreach (string key in nvc.AllKeys)
    {
        Console.WriteLine(key + ":" + nvc[key]);
    }

    //讀取男人
    IDictionary dict = (IDictionary)ConfigurationManager.GetSection("Man");
    foreach (string key in dict.Keys)
    {
        Console.WriteLine(key + ":" + dict[key]);
    }

    IDictionary dict1 = (IDictionary)ConfigurationManager.GetSection("Name");
    foreach (string key in dict1.Keys)
    {
        Console.WriteLine(key + ":" + dict1[key]);
    }

    Console.ReadKey();
}
技術分享

  輸出結果如下:

  技術分享

  2、自定義Handler

  自定義讀取節點需要實現接口IConfigurationSectionHandler,並提供Create的具體實現。

  Appconfig代碼:

技術分享
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>    <!--後面的type是處理處理節點PersonHandler所在的位置第二個參數是程序集,你可以不要Version開始之後的-->
      <section name="Person" type="ConsoleApplication1.PersonHandler,ConsoleApplication1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" allowLocation="true" allowDefinition="Everywhere" />
  </configSections>
  <Person age="23" name="劉備" />
</configuration>
技術分享

  主程序代碼:

技術分享
  class Program
    {
        static void Main(string[] args)
        {
            Hashtable config = ConfigurationManager.GetSection("Person") as Hashtable;
            Console.WriteLine("節點數量是:" + config.Count);
            //2重鍵值對的方式,其中deKey又可以再次轉化為一個Hashtable
            foreach (DictionaryEntry deKey in config)
            {
                Console.WriteLine("屬性元素: " + deKey.Key.ToString());
                Hashtable attribs = (Hashtable)deKey.Value;
                foreach (DictionaryEntry deAttrib in attribs)
                {
                    Console.WriteLine(deAttrib.Key.ToString() + "=" + deAttrib.Value.ToString());
                }
            }

            Console.ReadKey();
        }
    }

    //註意必須要實現IConfigurationSectionHandler接口
    class PersonHandler : IConfigurationSectionHandler
    {
        public object Create(object parent, object configContext, System.Xml.XmlNode section)
        {
            Hashtable myConfig = new Hashtable();
            // 本節元素,獲取的任何屬性。
            Hashtable myAttribs = new Hashtable();
            //遍歷當前節點的屬性
            foreach (XmlAttribute attrib in section.Attributes)
            {
                //如果當前節點是屬性節點,則添加進入myAttribs
                if (XmlNodeType.Attribute == attrib.NodeType)
                {
                    myAttribs.Add(attrib.Name, attrib.Value);
                }
            }
            //把當前屬性節點集合添加進myConfig
            myConfig.Add(section.Name, myAttribs);
            return myConfig;
        }
    }
技術分享

  輸出結果如下:

  技術分享

  這樣的配置代碼看起來還是有點吃力,畢竟Hashtable的層次有兩層。

  3、property屬性的方式讀取

  1. 使用這種方法,需要自定義一個類,並且要繼承自ConfigurationSection基類。ConfigurationProperty的構造函數中傳入的name字符串將會用於config文件中,表示各參數的屬性名稱。
  2. 屬性的值的讀寫要調用this[]或base[],由基類去保存,請不要自行設計Field來保存。
  3. 為了能使用配置節點能被解析,需要在<configSections>中註冊: <section name="Person" type="ConsoleApplication1.PersonSection,ConsoleApplication1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" allowLocation="true" allowDefinition="Everywhere" /> ,且要註意name="Person"要與<Person ..... >是對應的。

  先來看看配置文件的寫法:

技術分享
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>    <!--後面的type是處理處理節點PersonSection所在的位置第二個參數是程序集,你可以不要Version開始之後的-->
      <section name="Person" type="ConsoleApplication1.PersonSection,ConsoleApplication1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" allowLocation="true" allowDefinition="Everywhere" />
  </configSections>
  <Person age="23" name="劉備" />
</configuration>
技術分享

  然後程序代碼:

技術分享
    class Program
    {
        static void Main(string[] args)
        {
            PersonSection person = ConfigurationManager.GetSection("Person") as PersonSection;
            Console.WriteLine("name={0},age={1}", person.Age, person.Name);

            Console.ReadKey();
        }
    }

    //註意 這裏是繼承自System.Configuration.ConfigurationSection了
    class PersonSection : System.Configuration.ConfigurationSection
    {
        [ConfigurationProperty("age", IsRequired = false, DefaultValue = 0)]
        public int Age
        {
            get { return (int)base["age"]; } 
            set { base["age"] = value; }
        }

        [ConfigurationProperty("name", IsRequired = false, DefaultValue = "")]
        public string Name
        {
            get { return (string)base["name"]; }
            set { base["name"] = value; }
        }
    }
技術分享

  輸出結果如下:

  技術分享

  4、配置子元素

  對於稍微在復雜一點的結構,子元素的Model類要繼承自ConfigurationElement。

  config文件代碼:

技術分享
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="complex" type="ConsoleApplication1.ComplexSection,ConsoleApplication1"/>
  </configSections>
  <complex height="182">
    <child firstName="張" lastName="飛"/>
  </complex>
</configuration>
技術分享

  主程序代碼:

技術分享
  class Program
    {
        static void Main(string[] args)
        {
            ComplexSection sec = ConfigurationManager.GetSection("complex") as ComplexSection;
            Console.WriteLine(sec.Height);          //訪問屬性
            Console.WriteLine(sec.Child.FirstName); //訪問子節點屬性
            Console.WriteLine(sec.Child.LastName);  //訪問子節點屬性

            Console.ReadKey();
        }
    }

    public class ComplexSection : ConfigurationSection
    {
        [ConfigurationProperty("height", IsRequired = true)]
        public int Height
        {
            get { return (int)base["height"]; }
            set { base["height"] = value; }
        }

        [ConfigurationProperty("child", IsDefaultCollection = false)]
        public ChildSection Child
        {
            get { return (ChildSection)base["child"]; }
            set { base["child"] = value; }
        }
    }

    public class ChildSection : ConfigurationElement
    {
        [ConfigurationProperty("firstName", IsRequired = true, IsKey = true)]
        public string FirstName
        {
            get { return (string)base["firstName"]; }
            set { base["firstName"] = value; }
        }

        [ConfigurationProperty("lastName", IsRequired = true)]
        public string LastName
        {
            get { return (string)base["lastName"]; }
            set { base["lastName"] = value; }
        }
    }
技術分享

  輸出結果如圖所示:

  技術分享

  5、配置文件中的CDATA

  有時候,在配置文件裏可能會包含一些比較復雜的代碼段,這時候就要用到XML的CDATA了。

技術分享
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="MySection" type="ConsoleApplication1.MySection, ConsoleApplication1" />
  </configSections>
  <MySection>
    <HTML>
      <![CDATA[
          <div style="# font-size:24px">加粗顯示</div>
      ]]>
    </HTML>
    <SQL>
      <![CDATA[
          SELECT TOP 10 * FROM Person
      ]]>
    </SQL>
  </MySection>
</configuration>
技術分享

  主程序代碼如下:

技術分享
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MySection section = ConfigurationManager.GetSection("MySection") as MySection;
            Console.WriteLine("{0}{1}", section.HTML.CommandText, section.SQL.CommandText);

            Console.ReadKey();
        }
    }

    //註意 這裏是繼承自System.Configuration.ConfigurationSection了
    class MySection : System.Configuration.ConfigurationSection
    {
        [ConfigurationProperty("HTML", IsRequired = false)]
        public MyTextElement HTML
        {
            get { return (MyTextElement)base["HTML"]; }
            set { base["HTML"] = value; }
        }

        [ConfigurationProperty("SQL", IsRequired = false)]
        public MyTextElement SQL
        {
            get { return (MyTextElement)base["SQL"]; }
            set { base["SQL"] = value; }
        }
    }

    public class MyTextElement : ConfigurationElement
    {
        protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey)
        {
            CommandText = reader.ReadElementContentAs(typeof(string), null) as string;
        }
        protected override bool SerializeElement(System.Xml.XmlWriter writer, bool serializeCollectionKey)
        {
            if (writer != null)
            {
                writer.WriteCData(CommandText);
            }
            return true;
        }

        [ConfigurationProperty("data", IsRequired = false)]
        public string CommandText
        {
            get { return this["data"].ToString(); }
            set { this["data"] = value; }
        }
    }
}
技術分享

  輸出如下:

  技術分享

  6、配置元素Collection

  類似下面的配置方式,在ASP.NET的HttpHandler, HttpModule中太常見了。

技術分享
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="MySection" type="ConsoleApplication1.MySection, ConsoleApplication1" />
  </configSections>
  <MySection>
    <add key="a" value="劉備"></add>
    <add key="b" value="關羽"></add>
    <add key="c" value="張飛"></add>
  </MySection>
</configuration>
技術分享

  實現代碼如下:

技術分享
    class Program
    {
        static void Main(string[] args)
        {
            MySection section = ConfigurationManager.GetSection("MySection") as MySection;
            foreach (MyKeyValueSetting add in section.KeyValues)
            {
                Console.WriteLine(add.Key + ":" + add.Value);
            }

            Console.ReadKey();
        }
    }

    public class MySection : ConfigurationSection    // 所有配置節點都要選擇這個基類
    {
        private static readonly ConfigurationProperty s_property = new ConfigurationProperty(string.Empty, typeof(MyKeyValueCollection), null, ConfigurationPropertyOptions.IsDefaultCollection);

        [ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
        public MyKeyValueCollection KeyValues
        {
            get
            {
                return (MyKeyValueCollection)base[s_property];
            }
        }
    }

    [ConfigurationCollection(typeof(MyKeyValueSetting))]
    public class MyKeyValueCollection : ConfigurationElementCollection        // 自定義一個集合
    {
        // 基本上,所有的方法都只要簡單地調用基類的實現就可以了。
        public MyKeyValueCollection() : base(StringComparer.OrdinalIgnoreCase)    // 忽略大小寫
        {

        }

        // 其實關鍵就是這個索引器。但它也是調用基類的實現,只是做下類型轉就行了。
        new public MyKeyValueSetting this[string name]
        {
            get { return (MyKeyValueSetting)base.BaseGet(name); }
        }

        // 下面二個方法中抽象類中必須要實現的。
        protected override ConfigurationElement CreateNewElement()
        {
            return new MyKeyValueSetting();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((MyKeyValueSetting)element).Key;
        }

        // 說明:如果不需要在代碼中修改集合,可以不實現Add, Clear, Remove
        public void Add(MyKeyValueSetting setting)
        {
            this.BaseAdd(setting);
        }

        public void Clear()
        {
            base.BaseClear();
        }

        public void Remove(string name)
        {
            base.BaseRemove(name);
        }
    }

    public class MyKeyValueSetting : ConfigurationElement    // 集合中的每個元素
    {
        [ConfigurationProperty("key", IsRequired = true)]
        public string Key
        {
            get { return this["key"].ToString(); }
            set { this["key"] = value; }
        }

        [ConfigurationProperty("value", IsRequired = true)]
        public string Value
        {
            get { return this["value"].ToString(); }
            set { this["value"] = value; }
        }
    }
技術分享

  輸出如下:

  技術分享

  小結:

  1. 為每個集合中的參數項創建一個從ConfigurationElement繼承的派生類。
  2. 為集合創建一個從ConfigurationElementCollection繼承的集合類,具體在實現時主要就是調用基類的方法。
  3. 在創建ConfigurationSection的繼承類時,創建一個表示集合的屬性就可以了,註意[ConfigurationProperty]的各參數。

  7、配置節點的寫入

  寫入配置節點的示例如下:

    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    PersonSection Section = config.GetSection("Person") as PersonSection;
    Section.Name = "撼地神牛";
    Section.Age = 10000;
    config.Save();
    ConfigurationManager.RefreshSection("Person");  //讓修改之後的結果生效

  在修改配置節點前,我們需要調用ConfigurationManager.OpenExeConfiguration(),然後調用config.GetSection()在得到節點後,轉成我們定義的節點類型, 然後就可以按照強類型的方式來修改我們定義的各參數項,最後調用config.Save();即可。

  註意:

  1. .net為了優化配置節點的讀取操作,會將數據緩存起來,如果希望使用修改後的結果生效,您還需要調用ConfigurationManager.RefreshSection(".....")。
  2. 如果是修改web.config,則需要使用 WebConfigurationManager。

  8、讀取.Net Framework中已經定義的節點

  .Net Framework已定義節點的讀取很簡單:

  <system.web>
    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </httpModules>
  </system.web>

  主程序如下:

技術分享
public ActionResult Index()
    {
        HttpModulesSection section = ConfigurationManager.GetSection("system.web/httpModules") as HttpModulesSection;
        foreach (HttpModuleAction action in section.Modules)
        {
            Response.Write(action.Name + "<br/>");
        }
        return Content("");
    }
技術分享

  輸出如下:

  技術分享

  註意,連服務器上mechine裏面的配置都會一起讀出來。

  在Web.config裏是只讀的,寫不了,而非Web程序的寫與上面的例子一樣,此處不再復述。

http://www.cnblogs.com/kissdodog/archive/2013/04/11/3014227.html

配置文件的讀寫