如何自定義配置節點

目錄
  1. 向項目中添加System.Configuration引用。ConfigurationSection、ConfigurationElement、ConfigurationElementCollection這幾個類都是在System.Configuration中定義的,而該dll默認並不是新建一個項目就有的,需要添加該dll引用。
  2. 假如我們要配置的節點格式如下:
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3.   <configSections>
  4.       <section name="SingleSectionHandler" type="CustomSingleSection.SingleSectionHandler, CustomSingleSection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  5.   </configSections>
  6.   <SingleSectionHandler myAttrib1="lastBeachhead">
  7.     <MySingleSection MyAttribute1="softwarezxj" MyAttribute2="epms"/>
  8.    </SingleSectionHandler>
  9. </configuration>
    從配置信息可以看出,我們需要實現一個類CustomSingleSection.SingleSectionHandler,該類有2個屬性,一個屬性類型爲string,名稱爲myAttrib1,另外一個屬性類型爲MySingleSection,類型MySingleSection有2個string類型的屬性。因爲MySingleSection下並沒有子節點,故該類需要繼承自CongigurationElement,而SingleSectionHandler因爲是一個section,所以該類需要繼承自System.ConfigurationSection。
    具體的實現代碼如下:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Configuration;
  6. namespace CustomSingleSection
  7. {
  8.     public class SingleSectionHandler : ConfigurationSection
  9.     {
  10.         public SingleSectionHandler()
  11.         {
  12.         }
  13.         public SingleSectionHandler(String attribVal)
  14.         {
  15.             MyAttrib1 = attribVal;
  16.         }
  17.         [ConfigurationProperty("myAttrib1", DefaultValue = "默認值", IsRequired = true)]
  18.         [StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;'/"|//", MinLength = 1, MaxLength = 60)]
  19.         public String MyAttrib1
  20.         {
  21.             get { return (String)this["myAttrib1"]; }
  22.             set { this["myAttrib1"] = value; }
  23.         }
  24.         [ConfigurationProperty("MySingleSection")]
  25.         public MySingleSection MySingleSection
  26.         {
  27.             get
  28.             {
  29.                 return (MySingleSection)this["MySingleSection"]; 
  30.             }
  31.             set
  32.             {
  33.                 this["MySingleSection"] = value; 
  34.             }
  35.         }
  36.     }
  37.     public class MySingleSection : ConfigurationElement 
  38.     {
  39.         public MySingleSection()
  40.         {
  41.         }
  42.         public MySingleSection(String a1, String a2)
  43.         {
  44.             MyAttribute1 = a1;
  45.             MyAttribute2 = a2;
  46.         }
  47.         [ConfigurationProperty("MyAttribute1", DefaultValue = "默認屬性1", IsRequired = true)]
  48.         [StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;'/"|//", MinLength = 1, MaxLength = 60)]
  49.         public String MyAttribute1
  50.         {
  51.             getreturn (String)this["MyAttribute1"]; }
  52.             setthis["MyAttribute1"] = value; }
  53.         }
  54.         [ConfigurationProperty("MyAttribute2", DefaultValue = "默認屬性2", IsRequired = true)]
  55.         [StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;'/"|//", MinLength = 1, MaxLength = 60)]
  56.         public String MyAttribute2
  57.         {
  58.             getreturn (String)this["MyAttribute2"]; }
  59.             setthis["MyAttribute2"] = value; }
  60.         }
  61.     }
  62. }
   從代碼裏可以看出了各個基類本身已經有了索引器。另外需要注意的是,配置的信息都是大小寫敏感的。比如我們在類SingleSectionHandler中定義了屬性MyAttrib1的標籤[ConfigurationProperty("myAttrib1", DefaultValue = "默認值", IsRequired = true)],那麼在config文件中屬性的名字就必須是myAttrib1,大小寫不能寫錯,而且MyAttrib1屬性的實現中,使用索引器的時候也必須是get { return (String)this["myAttrib1"]; } set { this["myAttrib1"] = value; },索引器中的鍵名如果不是myAttrib1,即跟config中的屬性名稱不一樣,那也是運行不成功的。
   使用該配置的代碼如下:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Configuration;
  6. namespace CustomSingleSection
  7. {
  8.     class Program
  9.     {
  10.         static void Main(string[] args)
  11.         {
  12.             LookCustomSingleSection();
  13.             Console.ReadLine();
  14.         }
  15.         private static void LookCustomSingleSection() 
  16.         {
  17.             SingleSectionHandler mySingleSection = ConfigurationManager.GetSection("SingleSectionHandler"as SingleSectionHandler;
  18.             StringBuilder sb = new StringBuilder();
  19.             sb.Append("該自定義配置節的屬性MyAttrib1的值是:");
  20.             sb.Append(mySingleSection.MyAttrib1.ToString());
  21.             sb.Append("/n");
  22.             sb.Append("該自定義配置節的MySingleConfigElement節點的MyAttribute1屬性的值是:");
  23.             sb.Append( mySingleSection.MySingleSection.MyAttribute1.ToString() );
  24.             sb.Append("/n");
  25.             sb.Append("該自定義配置節的MySingleConfigElement節點的MyAttribute2屬性的值是:");
  26.             sb.Append(mySingleSection.MySingleSection.MyAttribute2.ToString());
  27.             sb.Append("/n");
  28.             Console.WriteLine( sb.ToString() );
  29.         }
  30.     }
  31. }

   舉例說明,假如我們需要實現一個如下的配置:
  1. <customMulSectionDemo>
  2.     <regexUrlMapping enable="true" rebaseClientPath="true">
  3.       <add url="(/d+)$" mappedUrl="default.aspx?id=$1"></add>
  4.       <add url="/$" mappedUrl="default.aspx?id=0"></add>
  5.     </regexUrlMapping>
  6. </customMulSectionDemo>
    在這裏customMulSectionDemo就是我們要定義的配置節,而配置節裏面又包含一個regexUrlMapping元素,該元素有兩個屬性和一些子元素,我們選擇的子元素比較特殊,它是n個add元素。使用的形式跟assSettings元素下面的add元素類似。那麼如何實現這個自定義配置呢?
    首先需要定義一個配置節元素,如下:
  1. <configSections>
  2.     <section name="customMulSectionDemo" type="CustomMulSection.RegexUrlMappingConfig,CustomMulSection" allowDefinition="Everywhere" restartOnExternalChanges="true" allowLocation="true"/>
  3. </configSections>
    在這裏,我們只講解name和type屬性的使用,其它屬性的用法請參閱MSDN。name屬性表示自定義配置節元素的名稱。Type表示應該由哪個dll下哪個命名空間的哪個類來處理這個配置節。如上例中所寫,CustomMulSection是dll的名稱(可以從AssemblyInfo.cs文件中找到),CustomMulSection.RegexUrlMappingConfig是處理該配置節的類的全名稱(包含命名空間)。
    Ok,我們已經把目的明確了,下面的工作就是要實現RegexUrlMappingConfig這個類。要想此類擁有處理配置節的能力,就必須裝飾一下這個類,裝飾完成後,此類的代碼如下:
  1. class RegexUrlMappingConfig : ConfigurationSection
  2.     {
  3.         [ConfigurationProperty("regexUrlMapping")]
  4.         public UrlMappingCollection UrlMappings
  5.         {
  6.             get{return this["regexUrlMapping"as UrlMappingCollection;}
  7.         }
  8.     }
    首先,我們的類應該從ConfigurationSection類繼承。這樣它就有了處理自定義配置信息的能力。由於我們的配置節中只有一個regexUrlMapping元素,而且此元素包含了很多add元素。這種情況下我們使用了一個名爲UrlMappings的屬性來表示這個集合。爲了表示該屬性和元素之間的映射關係,我們需要以ConfigurationProperty自定義屬性修飾UrlMappings。ConfigurationProperty類的參數” regexUrlMapping”指定了要映射的元素。get訪問器中的代碼非常程式化,這裏不講它的原理,只需要知道如此就可以實現對數據的訪問。
    下一步,就是實現UrlMappingCollection類。由名字可以得知,這是一個集合類,它一般用來處理包含add元素的元素。實現此類也需要使用自定義屬性對此類進行裝飾。如下:
  1. class UrlMappingCollection : ConfigurationElementCollection
  2.     {
  3.         protected override ConfigurationElement CreateNewElement()
  4.         {
  5.             return new UrlMapping();
  6.         }
  7.         protected override object GetElementKey(ConfigurationElement element)
  8.         {
  9.             return ((UrlMapping)element).Url;
  10.         }
  11.         [ConfigurationProperty("enable")]
  12.         public bool Enable
  13.         {
  14.             get
  15.             {
  16.                 return bool.Parse(this["enable"].ToString());
  17.             }
  18.         }
  19.         [ConfigurationProperty("rebaseClientPath")]
  20.         public bool RebaseClientPath
  21.         {
  22.             get
  23.             {
  24.                 return bool.Parse(this["rebaseClientPath"].ToString());
  25.             }
  26.         }
  27.         //寫一個索引器,方便的訪問該集合中的元素。
  28.         //如果不寫,則只有foreach來訪問。
  29.         public UrlMapping this[int index] 
  30.         {
  31.             get
  32.             {
  33.                 return this.BaseGet(index) as UrlMapping;
  34.             }
  35.         }
  36.     }
    可以看到,實現表示集合元素的類必須從ConfigurationElementCollection類繼承。並且必須提供CreateNewElement和GetElementKey兩個方法的重載。CreateNewElement其實是一個工廠方法,在此方法中,你必須返回一個表示一個add元素的對象,這樣系統才能從web.config讀取數據並形成一個集合。GetElementKey方法中,你需要返回一個可以表示爲add元素鍵值的屬性,方法的參數就是表示add元素的對象,該對象一定是從ConfigurationElement繼承的,所以我們可以將其轉換爲一個我們自定義的配置對象,然後訪問它的屬性。在示例中我們返回了add元素的url屬性值。因爲這個方法是拿到一個對象對應的key,所以經常被其它方法調用以獲取對象。
    現在,我們已經實現了需要重寫的方法。看到regexUrlMapping元素還包括兩個屬性,實現這兩個屬性的代碼與已講過的內容類似。在此不做贅述。
    還差最後一步,就是實現表示add元素的類。如下:
  1. class UrlMapping : ConfigurationElement
  2.     {
  3.         [ConfigurationProperty("mappedUrl")]
  4.         public string MappedUrl
  5.         {
  6.             get
  7.             {
  8.                 return (string)this["mappedUrl"];
  9.             }
  10.         }
  11.         [ConfigurationProperty("url")]
  12.         public string Url
  13.         {
  14.             get
  15.             {
  16.                 return (string)this["url"];
  17.             }
  18.         }
  19.     }
   唯一需要講述的就是這個類必須從ConfigurationElement繼承。其它的內容通過以上的講述應該能夠很好的理解。
   至此,我們已經完成了配置的映射工作。
   完整的代碼如下所示:
   app.config:
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3.   <configSections>
  4.     <section name="customMulSectionDemo" type="CustomMulSection.RegexUrlMappingConfig,CustomMulSection" allowDefinition="Everywhere" restartOnExternalChanges="true" allowLocation="true"/>
  5.   </configSections>
  6.   <customMulSectionDemo>
  7.     <regexUrlMapping enable="true" rebaseClientPath="true">
  8.       <add url="(/d+)$" mappedUrl="default.aspx?id=$1"></add>
  9.       <add url="/$" mappedUrl="default.aspx?id=0"></add>
  10.     </regexUrlMapping>
  11.   </customMulSectionDemo>
  12.   
  13. </configuration>
   配置相關的解釋類:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Configuration;
  6. namespace CustomMulSection
  7. {
  8.     class RegexUrlMappingConfig : ConfigurationSection
  9.     {
  10.         [ConfigurationProperty("regexUrlMapping")]
  11.         public UrlMappingCollection UrlMappings
  12.         {
  13.             get{return this["regexUrlMapping"as UrlMappingCollection;}
  14.         }
  15.     }
  16.     class UrlMappingCollection : ConfigurationElementCollection
  17.     {
  18.         protected override ConfigurationElement CreateNewElement()
  19.         {
  20.             return new UrlMapping();
  21.         }
  22.         protected override object GetElementKey(ConfigurationElement element)
  23.         {
  24.             return ((UrlMapping)element).Url;
  25.         }
  26.         [ConfigurationProperty("enable")]
  27.         public bool Enable
  28.         {
  29.             get
  30.             {
  31.                 return bool.Parse(this["enable"].ToString());
  32.             }
  33.         }
  34.         [ConfigurationProperty("rebaseClientPath")]
  35.         public bool RebaseClientPath
  36.         {
  37.             get
  38.             {
  39.                 return bool.Parse(this["rebaseClientPath"].ToString());
  40.             }
  41.         }
  42.         //寫一個索引器,方便的訪問該集合中的元素。
  43.         //如果不寫,則只有foreach來訪問。
  44.         public UrlMapping this[int index] 
  45.         {
  46.             get
  47.             {
  48.                 return this.BaseGet(index) as UrlMapping;
  49.             }
  50.         }
  51.     }
  52.     class UrlMapping : ConfigurationElement
  53.     {
  54.         [ConfigurationProperty("mappedUrl")]
  55.         public string MappedUrl
  56.         {
  57.             get
  58.             {
  59.                 return (string)this["mappedUrl"];
  60.             }
  61.         }
  62.         [ConfigurationProperty("url")]
  63.         public string Url
  64.         {
  65.             get
  66.             {
  67.                 return (string)this["url"];
  68.             }
  69.         }
  70.     }
  71. }

   測試代碼:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Configuration;
  6. namespace CustomMulSection
  7. {
  8.     class Program
  9.     {
  10.         static void Main(string[] args)
  11.         {
  12.             DealMulSection();
  13.             Console.ReadLine();
  14.         }
  15.         private static void DealMulSection() 
  16.         {
  17.             RegexUrlMappingConfig myCustomMulSection = ConfigurationManager.GetSection("customMulSectionDemo"as RegexUrlMappingConfig;
  18.             StringBuilder sb = new StringBuilder();
  19.             sb.Append("myCustomMulSection對象的regexUrlMapping屬性(實際是個集合)的enable:");
  20.             sb.Append(myCustomMulSection.UrlMappings.Enable.ToString());
  21.             sb.Append("/n");
  22.             sb.Append("myCustomMulSection對象的regexUrlMapping屬性(實際是個集合)的rebaseClientPath:");
  23.             sb.Append(myCustomMulSection.UrlMappings.RebaseClientPath.ToString());
  24.             sb.Append("/n");
  25.             for (int i = 0; i < myCustomMulSection.UrlMappings.Count; i++ )
  26.             {
  27.                 sb.Append("UrlMappings[");
  28.                 sb.Append(i.ToString());
  29.                 sb.Append("].url:");
  30.                 sb.Append(myCustomMulSection.UrlMappings[i].Url.ToString());
  31.                 sb.Append("/n");
  32.                 sb.Append("UrlMappings[");
  33.                 sb.Append(i.ToString());
  34.                 sb.Append("].mappedUrl:");
  35.                 sb.Append(myCustomMulSection.UrlMappings[i].MappedUrl.ToString());
  36.                 sb.Append("/n");
  37.             }
  38.             Console.WriteLine(sb.ToString());
  39.         }
  40.     }
  41. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章