天天看點

在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