擴展配置節

這章內容大部分摘自  .NET之美 這本書的!web

 <!--全部節點屬性 configSource 能夠將擴展文件放入外部-->服務器

咱們日常使用的appSettingsconnectionStrings,在webconfig中並無看到configSection節點 ,那是由哪一個類型處理的呢?這是由於它們的節點處理類型定義在了machine.config
app

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<configSections>
<section name="appSettings" type="System.Configuration.AppSettingsSecti
System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false"
requirePermission="false"/>
<section name="connectionStrings"
type="System.Configuration.ConnectionStringsSection, System.Configuration,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"requirePermission="false"/>
</configSections>
</configuration>

能夠看到,appSettings是由System.Configuration.AppSettingsSection類型處理的,connectionStrings則是由System.Configuration.ConnectionStringsSection類型處理的 ;
ide

另外再觀察一下machine.config就會發現,處理程序分紅了兩種類型:一種是以Section結尾的,好比AppSettingsSectionConnectionStringsSection這兩個;還有一種是ui

Handler結尾的,好比:
this

<section name="system.data.dataset"
type="System.Configuration.NameValueFileSectionHandler, System, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089" restartOnExternalChanges="false"/>

能夠看到type屬性System.Configuration.NameValueFileSectionHandler是以Handler結尾的。 之因此會有這樣的區別,是由於.NET中對於節點有兩種處理方式,一種是定義一個繼承自System.Configuration.ConfigurationSection的類,這也就是以Section結尾的類型;一種是實現System.Configuration.IConfigurationSectionHandler接口,也就是以Handler結尾的類型。 .NET Framework 2.0之後版本推薦採用繼承ConfigurationSection類的方式。 本章的示例大多數採用的是IConfigurationSectionHandler接口的方式,同時也會提供一個繼承
ConfigurationSection類的方式做爲對比。
type由兩部分組成,由逗號「,」分隔,前半部分是類型名稱,後半部分是類型所在的程序集名稱。
1、.NET內置處理程序
spa

.NET內置的處理程序定義於machine.config中,提供全局服務,無須進行任何額外工做就能夠直接使用。 可是使用內置節點在不少狀況下不必定方便,比方說,咱們
但願保存站點使用的郵件服務器的地址、 用戶名和密碼,那麼之前的作法,配置文件會是相似這樣的:
.net

<appSettings>
<add key="SiteName" value="TraceFact.Net"/>
<add key="Version" value="v1.0.08040301" />
<add key="GreetingLanguage" value="Chinese" />
<add key="MailServer" value="mail.tracefact.net" />
<add key="MailUser" value="jimmyzhang" />
<add key="MailPassword" value="123456"/>
</appSettings>

這樣看起來比較散亂:MailServerMailUserMailPassword很明顯是一組相關的數據,可是和其餘的配置混在了一塊兒。 若是能夠自定義一個節點,狀況就會好不少,好比:rest

<?xml version="1.0"?>
<configuration>
<!-- 其他略 -->
<mailServeraddress="mail.tracefact.net" userName="jimmyzhang" password="123456
</configuration

這樣看起來就行了不少,mailServer表示這是一個關於郵件服務器配置的節點,它的屬性/值分別表明存儲的相應值。  code

若是如今不作任何修改,直接運行程序,則會拋出異常未經處理的異常:System.Configuration.ConfigurationErrorsException:配置系統未能初始化---
>System.Configuration.ConfigurationErrorsException:沒法識別的配置節點mailServer。這是由於.NET底層的處理類型不認識這個節點。

爲了不發生這個錯誤,必須在configSection中指定對mailServer節點的處理程序 。有時候,咱們但願繞過.NET的機制,直接使用System.Xml命名空間下的類來對配置文件(App.config
也是標準的Xml文件)進行操做,可是由於這裏會報錯,因此有的人乾脆就新建一個xml文件,而後對新建的xml文件進行操做。  實際上,能夠經過指定IgnoreSectionHandler或者
IgnoreSection處理程序的方式來進行處理,如同它們的名稱所暗示的,這兩個處理程序什麼都不作,僅僅是讓.NET忽略自定義的配置節點。  修改App.config,在根節點configuration
建立configSections節點,而後再添加一個section節點,指定它的name屬性值爲mailServer,意爲指定mailServer節點的處理程序,而後指定typeSystem.Configuration.IgnoreSection

<?xml version="1.0"?>
<configuration>
<configSections>
<!-- 使用IgnoreSection,能夠將指定的XMl節點忽視掉 -->
<section name="mailServer" type="System.Configuration.IgnoreSection,System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" allowLocation="false"
restartOnExternalChanges="true" />
</configSections>
<!-- 自定義節點 mailServer -->
<mailServer address="mail.tracefact.net" userName="jimmyzhang" password="123456
</configuration>

此時再次運行程序,就不會再拋出異常了 ;

2、 使用自定義節點和自定義處理程序

假如站點更大一些,只使用一個郵件服務器壓力太大,須要設置多個郵件服務器,對於子域名forum.tracefact.net使用一個郵件服務器;對於blog.tracefact.net使用另外一個郵件
服務器,這時應如何設置App.config呢? 此時,就會須要相似下面這樣結構的配置:

<?xml version="1.0"?><configuration>
<!--使用自定義節點和自定義處理程序 -->
<mailServerGroup provider="www.edong.com">
<mailServer client="forum.tracefact.net">
<address>mail1.tracefact.net</address>
<userName>jimmyzhang</userName>
<password>123456</password>
</mailServer>
<mailServer client="blog.tracefact.com">
<address>mail2.tracefact.net</address>
<userName>webmaster</userName>
<password>456789</password>
</mailServer>
</mailServerGroup>
</configuration>

mailServerGroup節點包含了全部關於郵件服務器的信息。 它的provider屬性說明郵件服務器是由哪一個ISPInternet Service Provider互聯網服務供應商)提供的,這裏是中國易動
網(www.edong.com)。 其下的節點mailServer是指具體的郵件服務器,client說明此郵件服務器爲哪一個域名提供服務,address說明郵件服務器的地址,userNamepassword分別爲
用戶名和密碼。

處理方式有兩種,一種是實現IConfigurationSectionHandler接口,一種是繼承ConfigurationSection類。

1.0 自定義節點處理程序實現IConfigurationSectionHandler接口
IConfigurationSectionHandler接口的定義以下 :

  //
    // 摘要:
    //     處理對特定的配置節的訪問。
    public interface IConfigurationSectionHandler
    {
        //
        // 摘要:
        //     建立配置節處理程序。
        //
        // 參數:
        //   parent:
        //     父對象。
        //
        //   configContext:
        //     配置上下文對象。
        //
        //   section:
        //     節 XML 節點。
        //
        // 返回結果:
        //     建立的節處理程序對象。
        object Create(object parent, object configContext, XmlNode section);
    }

它只要求實現一個方法:Create(),當在ConfigurationManager對象上調用GetSection("sectionName")方法的時候,實際上會委託給這個Create()方法進行處理。 這個
方法最重要的一個參數是類型爲XmlNodesection,它表明着名爲"sectionName"的節點。它返回一個object類型的對象,這個對象一般是自定義的一個關於這個節點的配置對象,對
象的字段和屬性映射節點的屬性和文本值,用以提供強類型的訪問(也能夠返回一個Hashtable,這樣就無須自定義類型)。

節點在傳遞時有一個類型轉換,在調用GetSection()時,傳遞的是String類型的節點名稱;而在Create()方法中,傳遞的是該名稱的XmlNode類型的節點。

示例:

<!--配置-->
 <mailServerGroup provider="www.edong.com">
    <mailServer client="forum.tracefact.net">
      <address>mail1.tracefact.net</address>
      <userName>jimmyzhang</userName>
      <password>123456</password>
    </mailServer>
    <mailServer client="blog.tracefact.com">
      <address>mail2.tracefact.net</address>
      <userName>webmaster</userName>
      <password>456789</password>
    </mailServer>
  </mailServerGroup>

讀取方法:

    /// <summary>
    /// mailServerGroup 下面的各個MailServer節點
    /// </summary>
    public class MailServer
    {
        // 存儲mailServer的子節點(Address,UserName,Password)的innerText值
        // 以及屬性 Client 的值
        private Hashtable serverNode;
        public MailServer()
        {
            serverNode = new Hashtable();
        }

        public Hashtable ServerNode
        {
            get { return serverNode; }
        }
        public string Client
        {
            get { return serverNode["client"] as string; }
        }
        public string Address
        {
            get { return serverNode["address"] as string;}
        }
        public string UserName
        {
            get {return serverNode["userName"] as string;}
        }
        public string Password
        {
            get{ return serverNode["password"] as string;}
        }
    }
  /// <summary>
    ///這個類用於映射mailServerGroup總體節點。 對mailServerGroup節點的屬性以及子節點的訪問,均經過這個類來進行
    /// </summary>
    public class MailServerConfig : List<MailServer>
    {     
      public string Provider { get; set; }

    
    }
   public class MailServerConfigurationHandler : IConfigurationSectionHandler
    {
        /// <summary>
        /// // section 爲 MailServerGroup 節點,即根節點的位置
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="configContext"></param>
        /// <param name="section"></param>
        /// <returns></returns>
        public object Create(object parent, object configContext, XmlNode section)
        {
            // 設置方法返回配置對象,能夠是任何類型
            MailServerConfig config = new MailServerConfig();
         
            config.Provider = section.Attributes["provider"] == null ? "" : section.Attributes["provider"].Value;
          
            foreach (XmlNode child in section.ChildNodes)
            {
                MailServer server = new MailServer();
                if (child.Attributes["client"] != null)
                {
                    server.ServerNode.Add("client", child.Attributes["client"].Value);
                }
                // 獲取MailServer下的 Name,UserName,Password 節點
                foreach (XmlNode grandChild in child.ChildNodes)
                {
                    // 添加文本
                    server.ServerNode.Add(grandChild.Name, grandChild.InnerText);
                } 
                // 將server加入MailServerConfig
                config.Add(server);
            }
            return config;
        }
    }

使用:

     MailServerConfig serverGroup = (MailServerConfig)ConfigurationManager.GetSection("mailServerGroup");
            Console.WriteLine("使用自定義節點和自定義處理程序");
            Console.WriteLine("Provider:".PadRight(12, ' ') + serverGroup.Provider);
            foreach (MailServer config in serverGroup)
            {
                Console.WriteLine("--------------------------------------------");
                Console.WriteLine("Client:".PadRight(12, ' ') + config.Client);
                Console.WriteLine("Address:".PadRight(12, ' ') + config.Address);
                Console.WriteLine("User Name:".PadRight(12, ' ') + config.UserName);
                Console.WriteLine("PassWord:".PadRight(12, ' ') + config.Password);
            }

            Console.ReadKey();

2.自定義節點處理程序繼承ConfigurationSection基類 ;示例以下:

 

 <mailServerGroup2  provider="www.edong.com" >
    <mailServers>
      <mailServer
      client="forum.tracefact.net"
      address="mail1.tracefact.net"
      userName="jimmyzhang"
      password="123456" />
      <mailServer
      client="blog.tracefact.net"
      address="mail2.tracefact.net"
      userName="webmaster"
      password="456789" />
    </mailServers>
  </mailServerGroup2>
/// <summary>
    /// MailServer 節點; 這裏面的對應咱們配置文件節點的屬性
    /// </summary>
    public class MailServerElement : ConfigurationElement
    {
      
        [ConfigurationProperty("client", IsKey = true, IsRequired = true)]
        public string Client
        {
            get { return this["client"] as string; }
            set { this["client"] = value; }
        }
        [ConfigurationProperty("address")]
        public string Address
        {
            get { return this["address"] as string; }
            set { this["address"] = value; }
        }
        [ConfigurationProperty("userName")]
        public string UserName
        {
            get { return this["userName"] as string; }
            set { this["userName"] = value; }
        }
        [ConfigurationProperty("password")]
        public string Password
        {
            get { return this["password"] as string; }
            set { this["password"] = value; }
        }

    } /// <summary>    ///MailServer 集合類;通常狀況下重寫CreateNewElement,GetElementKey方法和用索引獲取便可
/// </summary>
  [ConfigurationCollection(typeof(MailServer), AddItemName = "mailServer")]
public class MailServerCollection : ConfigurationElementCollection { public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } protected override ConfigurationElement CreateNewElement() { return new MailServerElement(); } /// <summary> /// 獲取元素的key /// </summary> /// <param name="element"></param> /// <returns></returns> protected override object GetElementKey(ConfigurationElement element) { return ((MailServerElement)element).Client; } protected override string ElementName { get { return "mailServer"; } } public new int Count { get { return base.Count; } } public MailServerElement this[int index] { get { return (MailServerElement)BaseGet(index); } set { if (BaseGet(index) != null) { BaseRemoveAt(index); } BaseAdd(index, value); } } new public MailServerElement this[string Name] { get { return (MailServerElement)BaseGet(Name); } } public int IndexOf(MailServerElement element) { return BaseIndexOf(element); } public void Add(MailServerElement element) { BaseAdd(element); } public void Remove(MailServerElement element) { if (BaseIndexOf(element) >= 0) BaseRemove(element.Client); } public void RemoveAt(int index) { BaseRemoveAt(index); } public void Remove(string client) { BaseRemove(client); } public void Clear() { BaseClear(); } }
  public class MailServerSection:System.Configuration.ConfigurationSection
    {
        [ConfigurationProperty("provider", IsKey = true)]
        public string Provider { get { return this["provider"] as string; } }
        [ConfigurationProperty("mailServers", IsDefaultCollection = false)]
        public MailServerCollection MailServers
        {
            get
            {
                return (MailServerCollection)this["mailServers"];
            }
            set
            {
                this["mailServers"] = value;
            }
        }

    }

使用:

    MailServerSection mailSection = (MailServerSection)ConfigurationManager.GetSection("mailServerGroup2");
            Console.WriteLine("使用自定義節點和自定義處理程序");
            Debugger.Break();
            Console.WriteLine("Provider:".PadRight(12, ' ') + mailSection.Provider);
            foreach (MailServerElement config in mailSection.MailServers)
            {
                Console.WriteLine("--------------------------------------------");
                Console.WriteLine("Client:".PadRight(12, ' ') + config.Client);
                Console.WriteLine("Address:".PadRight(12, ' ') + config.Address);
                Console.WriteLine("User Name:".PadRight(12, ' ') + config.UserName);
                Console.WriteLine("PassWord:".PadRight(12, ' ') + config.Password);
            }

            Console.ReadKey();
相關文章
相關標籤/搜索