在进行C#项目开发过程中,随着项目的越来越大,越来越复杂。而在项目中用的配置数据也会越来越大,而且在协作开发过程中有些配置是可以共用的。如果没有相应的管理那么Config自定义的配置就会杂乱无章,不方便管理和维护。而我们可以通过自定义配置文件 configSections 节点在实现配置文件标准化。下面我们就讲解如何自定义 configSections。
首先我们先来看下config 的配置结构图:
我们自定义 configSections 节点:<section name="Channel.Machines" type="Chasel.Utility.MachineSectionElement,Chasel.Utility"/> 其中“Channel.Machines”就是下面<Channel.Machines>*****</Channel.Machines>这部分的名称。 type值: Chasel.Utility.MachineSectionElement 是我们自定义的 ConfigurationSection对象(记得带上命名空间), Chasel.Utility 是我们自定义 ConfigurationSection 对象所在项目的名称。
<Channel.Machines>*****</Channel.Machines>这部分才是我们真正自定义配置项的地方,其中 <machines>****</machines> 节点名称是我们自定义 ConfigurationElementCollection 对象时规定的,其值可以任意取。而 <machines>****</machines> 中的节点 <machine name=“key” key**=“value**”></machine> 节点则是我们配置具体实现的地方,其中每个 machine 都要有一个唯一标示的名字,用以区分不同 machine 的节点。在machine 节点中,我们使用 name 值作为该节点的唯一标示,host、uid、pwd 则是我们这条记录要配置的值。
我们看下自定义对象的实现:
MachineElement 、MachineElementCollection 、 MachineSectionElement 三个自定义对象定义如下:
1 // <summary> 2 /// 自定义ConfigurationElement 节点对象 3 /// </summary> 4 public class MachineElement:ConfigurationElement 5 { 6 [ConfigurationProperty("name",IsRequired=true,IsKey=true)] 7 public string Name 8 { 9 get { return (string)this["name"]; } 10 } 11 12 [ConfigurationProperty("host",IsRequired=true)] 13 public string Host 14 { 15 get { return (string)this["host"]; } 16 } 17 18 [ConfigurationProperty("uid",IsRequired=true)] 19 public string UID 20 { 21 get { return (string)this["uid"]; } 22 } 23 24 [ConfigurationProperty("pwd",IsRequired=true)] 25 public string PWD 26 { 27 get { return (string)this["pwd"]; } 28 } 29 30 }
MachineElementCollection对象:
1 /// <summary> 2 /// 自定义配置记录节点对象集合 3 /// </summary> 4 public class MachineElementCollection:ConfigurationElementCollection 5 { 6 /// <summary> 7 /// 重载生成ConfigurationElement 节点方法 8 /// </summary> 9 /// <returns></returns> 10 protected override ConfigurationElement CreateNewElement() 11 { 12 return new MachineElement(); 13 } 14 15 /// <summary> 16 /// 将ConfigurationElement 转换成自定义的对象 17 /// </summary> 18 /// <param name="element"></param> 19 /// <returns></returns> 20 protected override object GetElementKey(ConfigurationElement element) 21 { 22 MachineElement machine = element as MachineElement; 23 24 if(null==machine) 25 throw new ArgumentNullException("element is not MachineElement"); 26 27 return machine.Name; 28 } 29 30 public override ConfigurationElementCollectionType CollectionType 31 { 32 get 33 { 34 return ConfigurationElementCollectionType.BasicMap; 35 } 36 } 37 38 /// <summary> 39 /// ConfigurationElement节点对应的名称 40 /// </summary> 41 protected override string ElementName 42 { 43 get 44 { 45 return "machine"; 46 } 47 } 48 49 /// <summary> 50 /// 根据唯一标示的名称获取自定义ConfigurationElement节点对象 51 /// </summary> 52 /// <param name="name"></param> 53 /// <returns></returns> 54 public MachineElement Get(string name) 55 { 56 return (MachineElement)BaseGet(name); 57 } 58 }
MachineSectionElement对象:
1 /// <summary> 2 /// 自定义Section节点对象 3 /// </summary> 4 public class MachineSectionElement:ConfigurationSection 5 { 6 /// <summary> 7 /// Section 节点集合对应的名称 8 /// </summary> 9 [ConfigurationProperty("machines")] 10 public MachineElementCollection Machines 11 { 12 get { return (MachineElementCollection)this["machines"]; } 13 } 14 }
MachineElement对象中定义的属性就是 <machine>节点中的值。 其中我定义了 name作为节点的唯一标示 IsKey=true,而且每个 属性值都是必须的,所有设置了 IsRequired=true
MachineElementCollection对象 重载的ElementName属性,定义了节点的名称为 “machine”。其Get 方法则通过 节点中 name值获取 machine 节点
MachineSectionElement对象 声明了节点集合所在的节点名称 machines
下面我来使用我们自定义的配置对象值
1 var section = ConfigurationManager.GetSection("Channel.Machines") as MachineSectionElement; 2 3 Console.WriteLine(section.Machines.Get("Test1").Host);
大致对应的关系如图: