天天看点

在Web.config或App.config中的添加自定义配置

.Net中的System.Configuration命名空间为我们在web.config或者app.config中自定义配置提供了完美的支持。最近看到一些项目中还在自定义xml文件做程序的配置,所以忍不住写一篇用系统自定义配置的随笔了。

如果你已经对自定义配置了如指掌,请忽略这篇文章。

言归正传,我们先来看一个最简单的自定义配置

<code>&lt;?</code><code>xml</code> <code>version="1.0" encoding="utf-8" ?&gt;</code>

<code>&lt;</code><code>configuration</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>configSections</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>section</code> <code>name="simple" type="ConfigExample.Configuration.SimpleSection,ConfigExample"/&gt;</code>

<code>  </code><code>&lt;/</code><code>configSections</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>simple</code> <code>maxValue="20" minValue="1"&gt;&lt;/</code><code>simple</code><code>&gt;</code>

<code>&lt;/</code><code>configuration</code><code>&gt;</code>

在配置文件中使用自定义配置,需要在configSections中添加一个section元素,并制定此section元素对应的类型和名字。然后再在configuration根节点下面添加此自定义配置,如上例中的simple节点。simple节点只有两个整形数的属性maxValue和minValue。

要在程序中使用自定义配置我们还需要实现存取这个配置块的类型,一般需要做如下三件事:

1. 定义类型从System.Configuration.ConfigurationSection继承

2. 定义配置类的属性,这些属性需要用ConfigurationProperty特性修饰,并制定属性在配置节中的名称和其他一些限制信息

3. 通过基类的string索引器实现属性的get ,set

非常简单和自然,如下是上面配置类的实现:

<code>public</code> <code>class</code> <code>SimpleSection:System.Configuration.ConfigurationSection</code>

<code>{</code>

<code>    </code><code>[ConfigurationProperty(</code><code>"maxValue"</code><code>,IsRequired=</code><code>false</code><code>,DefaultValue=Int32.MaxValue)]</code>

<code>    </code><code>public</code> <code>int</code> <code>MaxValue</code>

<code>    </code><code>{</code>

<code>        </code><code>get</code>

<code>        </code><code>{</code>

<code>            </code><code>return</code>  <code>(</code><code>int</code><code>)</code><code>base</code><code>[</code><code>"maxValue"</code><code>];</code>

<code>        </code><code>}</code>

<code>        </code><code>set</code>

<code>            </code><code>base</code><code>[</code><code>"maxValue"</code><code>] = value;</code>

<code>    </code><code>}</code>

<code>    </code><code>[ConfigurationProperty(</code><code>"minValue"</code><code>,IsRequired=</code><code>false</code><code>,DefaultValue=1)]</code>

<code>    </code><code>public</code> <code>int</code> <code>MinValue</code>

<code>        </code><code>get</code> <code>{</code><code>return</code> <code>(</code><code>int</code><code>)</code><code>base</code><code>[</code><code>"minValue"</code><code>];}</code>

<code>        </code><code>set</code> <code>{</code><code>base</code><code>[</code><code>"minValue"</code><code>] = value; }</code>

<code>    </code><code>[ConfigurationProperty(</code><code>"enabled"</code><code>,IsRequired=</code><code>false</code><code>,DefaultValue=</code><code>true</code><code>)]</code>

<code>    </code><code>public</code> <code>bool</code> <code>Enable</code>

<code>            </code><code>return</code> <code>(</code><code>bool</code><code>)</code><code>base</code><code>[</code><code>"enabled"</code><code>];</code>

<code>            </code><code>base</code><code>[</code><code>"enabled"</code><code>] = value;</code>

<code>}</code>

这样子一个简单的配置类就完成了,怎么在程序中使用这个配置呢?需要使用ConfigurationManager类(要引用System.configuration.dll这个dll只有在.Net2.0之后的版本中才有)的GetSection方法获得配置就可以了。如下代码:

<code>SimpleSection simple = ConfigurationManager.GetSection(</code><code>"simple"</code><code>)</code><code>as</code> <code>SimpleSection;</code>

<code>Console.WriteLine(</code><code>"simple minValue={0} maxValue = {1}"</code><code>,simple.MinValue,simple.MaxValue);</code>

这个配置类太过简陋了,可能有时候我们还需要更复杂的构造,比如在配置类中使用类表示一组数据,下面我们看一个稍微复杂一点的自定义配置

<code>    </code><code>&lt;</code><code>section</code> <code>name="complex" type="ConfigExample.Configuration.ComplexSection,ConfigExample"/&gt;</code>

<code>  </code><code>&lt;</code><code>complex</code> <code>height="190"&gt;</code>

<code>    </code><code>&lt;</code><code>child</code> <code>firstName="James" lastName="Bond"/&gt;</code>

<code>  </code><code>&lt;/</code><code>complex</code><code>&gt;</code>

这个配置的名字是complex,他有一个属性height,他的节点内还有一个child元素这个元素有两个属性firstName和lastName;对于这个内嵌的节点该如何实现呢?首先我们需要定义一个类,要从ConfigurationElement类继承,然后再用和SimpleSection类似的方法定义一些用ConfigurationProperty特性修饰的属性就可以了,当然属性值的get,set也要使用基类的索引器。如下实现:

<code>public</code> <code>class</code> <code>ComplexSection : ConfigurationSection</code>

<code>    </code><code>[ConfigurationProperty(</code><code>"height"</code><code>, IsRequired =</code><code>true</code><code>)]</code>

<code>    </code><code>public</code> <code>int</code> <code>Height</code>

<code>            </code><code>return</code> <code>(</code><code>int</code><code>)</code><code>base</code><code>[</code><code>"height"</code><code>];</code>

<code>            </code><code>base</code><code>[</code><code>"height"</code><code>] = value;</code>

<code>    </code><code>[ConfigurationProperty(</code><code>"child"</code><code>, IsDefaultCollection =</code><code>false</code><code>)]</code>

<code>    </code><code>public</code> <code>ChildSection Child</code>

<code>            </code><code>return</code> <code>(ChildSection)</code><code>base</code><code>[</code><code>"child"</code><code>];</code>

<code>            </code><code>base</code><code>[</code><code>"child"</code><code>] = value;</code>

<code>public</code> <code>class</code> <code>ChildSection : ConfigurationElement</code>

<code>    </code><code>[ConfigurationProperty(</code><code>"firstName"</code><code>, IsRequired =</code><code>true</code><code>, IsKey =</code><code>true</code><code>)]</code>

<code>    </code><code>public</code> <code>string</code> <code>FirstName</code>

<code>            </code><code>return</code> <code>(</code><code>string</code><code>)</code><code>base</code><code>[</code><code>"firstName"</code><code>];</code>

<code>            </code><code>base</code><code>[</code><code>"firstName"</code><code>] = value;</code>

<code>    </code><code>[ConfigurationProperty(</code><code>"lastName"</code><code>, IsRequired =</code><code>true</code><code>)]</code>

<code>    </code><code>public</code> <code>string</code> <code>LastName</code>

<code>            </code><code>return</code> <code>(</code><code>string</code><code>)</code><code>base</code><code>[</code><code>"lastName"</code><code>];</code>

<code>            </code><code>base</code><code>[</code><code>"lastName"</code><code>] = value;</code>

还有稍微再复杂一点的情况,我们可能要在配置中配置一组相同类型的节点,也就是一组节点的集合。如下面的配置:

<code>    </code><code>&lt;</code><code>children</code><code>&gt;</code>

<code>      </code><code>&lt;</code><code>add</code> <code>firstName="Zhao" lastName="yukai"/&gt;</code>

<code>      </code><code>&lt;</code><code>add</code> <code>firstName="Lee" lastName="yukai"/&gt;</code>

<code>      </code><code>&lt;</code><code>remove</code> <code>firstName="Zhao"/&gt;</code>

<code>    </code><code>&lt;/</code><code>children</code><code>&gt;</code>

请看children节点,它就是一个集合类,在它里面定义了一组add元素,也可以有remove节点把已经添进去的配置去掉。

要使用自定义节点集合需要从ConfigurationElementCollection类继承一个自定义类,然后要实现此类GetElementKey(ConfigurationElement element)和ConfigurationElement CreateNewElement()两个方法;为了方便的访问子节点可以在这个类里面定义只读的索引器。请看下面的实现

<code>public</code> <code>class</code> <code>Children : ConfigurationElementCollection</code>

<code>    </code><code>protected</code> <code>override</code> <code>object</code> <code>GetElementKey(ConfigurationElement element)</code>

<code>        </code><code>return</code> <code>((ChildSection)element).FirstName;</code>

<code>    </code><code>protected</code> <code>override</code> <code>ConfigurationElement CreateNewElement()</code>

<code>        </code><code>return</code> <code>new</code> <code>ChildSection();</code>

<code>    </code><code>public</code> <code>ChildSection</code><code>this</code><code>[</code><code>int</code> <code>i]</code>

<code>            </code><code>return</code> <code>(ChildSection)</code><code>base</code><code>.BaseGet(i);</code>

<code>    </code><code>public</code> <code>ChildSection</code><code>this</code><code>[</code><code>string</code> <code>key]</code>

<code>            </code><code>return</code> <code>(ChildSection)</code><code>base</code><code>.BaseGet(key);</code>

当然要使用此集合类我们必须在Complex类中添加一个此集合类的属性,并要指定集合类的元素类型等属性,如下:

<code>[ConfigurationProperty(</code><code>"children"</code><code>, IsDefaultCollection =</code><code>false</code><code>)]</code>

<code>    </code><code>[ConfigurationCollection(</code><code>typeof</code><code>(ChildSection), CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap, RemoveItemName =</code><code>"remove"</code><code>)]</code>

<code>    </code><code>public</code> <code>Children Children</code>

<code>            </code><code>return</code> <code>(Children)</code><code>base</code><code>[</code><code>"children"</code><code>];</code>

<code>            </code><code>base</code><code>[</code><code>"children"</code><code>] = value;</code>

我们会经常用到类似appSettings配置节的键值对的构造,这时候我们就不必再自己实现了,我们可以直接使用现有的System.Configuration.NameValueConfigurationCollection类来定义一个自定义的键值对。可以在Complex类中定义如下属性

<code>[ConfigurationProperty(</code><code>"NVs"</code><code>, IsDefaultCollection =</code><code>false</code><code>)]</code>

<code>    </code><code>public</code> <code>System.Configuration.NameValueConfigurationCollection NVs</code>

<code>            </code><code>return</code> <code>(NameValueConfigurationCollection)</code><code>base</code><code>[</code><code>"NVs"</code><code>];</code>

<code>            </code><code>base</code><code>[</code><code>"NVs"</code><code>] = value;</code>

然后在配置文件的complex节中添加键值对配置

<code>&lt;</code><code>NVs</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>add</code> <code>name="abc" value="123"/&gt;</code>

<code>    </code><code>&lt;</code><code>add</code> <code>name="abcd" value="12d3"/&gt;</code>

<code>&lt;/</code><code>NVs</code><code>&gt;</code>

到这儿已经基本上可以满足所有的配置需求了。不过还有一点更大但是不复杂的概念,就是sectionGroup。我们可以自定义SectionGroup,然后在sectionGroup中配置多个section;分组对于大的应用程序是很有意义的。

如下配置,配置了一个包含simple和一个complex两个section的sectionGroup

<code>    </code><code>&lt;</code><code>sectionGroup</code> <code>type="ConfigExample.Configuration.SampleSectionGroup,ConfigExample" name="sampleGroup"&gt;</code>

<code>      </code><code>&lt;</code><code>section</code> <code>type="ConfigExample.Configuration.SimpleSection,ConfigExample" allowDefinition="Everywhere" name="simple" /&gt;</code>

<code>      </code><code>&lt;</code><code>section</code> <code>type="ConfigExample.Configuration.ComplexSection,ConfigExample" allowDefinition="Everywhere" name="complex"/&gt;</code>

<code>    </code><code>&lt;/</code><code>sectionGroup</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>sampleGroup</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>simple</code> <code>maxValue="20" minValue="1"&gt;</code>

<code>    </code><code>&lt;/</code><code>simple</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>complex</code> <code>height="190"&gt;</code>

<code>      </code><code>&lt;</code><code>child</code> <code>firstName="James" lastName="Bond"/&gt;</code>

<code>      </code><code>&lt;</code><code>children</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>add</code> <code>firstName="Zhao" lastName="yukai"/&gt;</code>

<code>        </code><code>&lt;</code><code>add</code> <code>firstName="Lee" lastName="yukai"/&gt;</code>

<code>        </code><code>&lt;</code><code>remove</code> <code>firstName="Zhao"/&gt;</code>

<code>      </code><code>&lt;/</code><code>children</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>NVs</code><code>&gt;</code>

<code>  </code><code>&lt;/</code><code>NVs</code><code>&gt;</code>

<code>    </code><code>&lt;/</code><code>complex</code><code>&gt;</code>

<code>  </code><code>&lt;/</code><code>sampleGroup</code><code>&gt;</code>

为了方便的存取sectionGroup中的section我们可以实现一个继承自System.Configuration.ConfigurationSectionGroup类的自定义类。实现很简单,就是通过基类的Sections[“sectionName”]索引器返回Section。如下:

<code>public</code> <code>class</code> <code>SampleSectionGroup : System.Configuration.ConfigurationSectionGroup</code>

<code>    </code><code>public</code> <code>SimpleSection Simple</code>

<code>            </code><code>return</code> <code>(SimpleSection)</code><code>base</code><code>.Sections[</code><code>"simple"</code><code>];</code>

<code>    </code><code>public</code> <code>ComplexSection Complex</code>

<code>            </code><code>return</code> <code>(ComplexSection)</code><code>base</code><code>.Sections[</code><code>"complex"</code><code>];</code>

需要注意的是SectionGroup不能使用ConfigurationManager.GetSection(string)方法来获得,要获得sectionGroup必须通过Configuration类的SectionGroups[string]索引器获得,如下示例代码:

<code>SampleSectionGroup sample = (SampleSectionGroup)ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).SectionGroups[</code><code>"sampleGroup"</code><code>];</code>

总结:

.Net framework给我们提供了一套很方便的配置库,我们只需要继承对应的类简单的配置一下就可以方便的使用在web.config或者app.config中配置的自定义节点了。

<a target="_blank" href="http://files.cnblogs.com/yukaizhao/ConfigExample.zip">自定义配置文件节源码</a>

来自:http://www.cnblogs.com/yukaizhao/archive/2011/12/02/net-web-config-costom-config-implement.html