如何自定义配置节点

目录
  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. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章