2009年7月30日 星期四

探討.NET Configuration Files 1-3

RunPC 112、113期:在.NET上保存應用程式設定(四)

ConfigurationSettings類別
ConfigurationSettings是一個類別提供在指定配置區段中對配置設定的存取,它擁有一個靜態方法(Static Method)GetConfig與一個靜態屬性(Static Property) AppSettings,是故可在不建立類別實體(Instance)的情況下即可使用該靜態方法與屬性,如上範例我們並未建立ConfigurationSettings實體而直接使用;AppSettings屬性會取得一個唯讀的NameValueCollection,含有配置區段中設定的名稱/值對;若在配置檔案中並未指定則會傳回empty;而GetConfig靜態方法的簽名碼(Signature)中指定傳回的是Object,但一般會是NameValueCollection,而實際上在區段中取得的會是ReadOnlyNameValueCollection,詳細的ConfigurationSettings類別請見configurationsettings.cs附檔。
為自訂標記(Tag)自訂一個處理器類別(Handler)
上面我們各舉了一個利用電腦配置檔系統事先已宣告的appSettings區段,和一個利用系統提供的處理器類別宣告一個自訂的區段,而這都不外乎是一種簡單的Key/Value配對機制,對於在共通上保留應用程式的設定值已經非常完美,但若遇到複雜的儲存值時卻也有點顯的不符使用,是故我們在這系列文章中的第二篇為各位介紹怎麼自訂一個XML的配置檔案,當然這是一個解決方式,但若可以利用.NET所提供的機制來解決這方面的問題那就更加的完美。接下來我們將為各位介紹怎麼為自訂標記自訂一個處理器類別,我們舉個簡單的例子,若有某甲公司想將有關產品分類、產品分類網址與產品項目的列表要保留於配置檔案中,其步驟如下:
1、 定義配置檔案內的XML結構描述
依上述需求我們會規劃其XML格式片段如下,顯然地我們沒法使用系統提供的處理器類別來加以剖析處理,接著我們將下面XML片斷加入Web.Config的根項目下,接著執行會發生如(圖一)的錯誤。

2、 建立自訂處理器
建立一個自訂處理器並不困難,但它必需是一個獨立的專案。
A、 在ProWebConfig專案內選擇功能表上的[專案]-->[新增]-->[專案],在新增專案對話盒中選[Visual Basic專案]-->[類別庫],名稱改為[ProProductHandler],記得點選[加入至方案]後按確定。
B、 在專案總管中刪除Class1.vb,後再專案上按右鍵選[加入新項目],選[類別]更名為[ProductTagHandler.vb]。
C、 自訂處理器類別必須實作IConfigurationSectionHandler介面,該介面只有一個Create的方法,由所有配置區段處理器實作以剖析配置區段的 XML。傳回的物件會加入至置配集合並且由 GetConfig進行存取。它帶有三個參數:parent、configContext、section,當然系統提供的處理器類別依舊是必需實作該介面[註3],請參考下面程式碼:

當應用程式剖析時,它會建立ProductTagHandler實體和呼叫Create方法,而通常我們只會用到section這個XmlNode參數,它包含了整個您要處理的配置檔區段內容,在這個例子上是指的區段內容;而configContext(HttpConfigurationContext)是提供目前的內容資訊給 ASP.NET 應用程式中的配置區段處理器,最主要是用來取得Web.config的虛擬路徑;parent則是在對應的父代配置區段中的配置設定。
[註3]:請參考附件系統提供處理器的原始碼檔案:dictionarysectionhandler.cs、ignoresectionhandler.cs、namevaluefilesectionhandler.cs、namevaluesectionhandler.cs、singletagsectionhandler.cs皆實作了IConfigurationSectionHandler介面。
D、 撰寫相關剖析程式碼,如下:

Imports System.Configuration
Imports System.Collections
Imports System.Xml
Public Class ProductTagHandler
Implements IConfigurationSectionHandler

Public Function Create(ByVal parent As Object, ByVal configContext As Object, ByVal section As System.Xml.XmlNode) As Object Implements System.Configuration.IConfigurationSectionHandler.Create
Dim xnProduct, xnRelProduct As XmlNode
Dim ProductNodes, RelProductNodes As XmlNodeList
Dim RelProducts, Prices As ArrayList
Dim PTitle, PDescUrl As String
Dim Products As New ArrayList()
'取得分類產品節點列表
ProductNodes = section.SelectNodes("Product")
'取得每個分類產品節點
For Each xnProduct In ProductNodes
'取得分類產品節點的Title、DescUrl屬性值
PTitle = xnProduct.Attributes.GetNamedItem("Title").Value
PDescUrl = xnProduct.Attributes.GetNamedItem("DescUrl").Value
RelProducts = New ArrayList()
Prices = New ArrayList()
'取出產品節點下的相關產品列表
RelProductNodes = xnProduct.SelectNodes("RelProducts//RelProduct")
If Not RelProductNodes Is Nothing Then
'取出相關產品的名稱與價格
For Each xnRelProduct In RelProductNodes
RelProducts.Add(xnRelProduct.InnerText)
Prices.Add(xnRelProduct.Attributes.GetNamedItem("Price").Value)
Next
End If
'將Product實體放入Products ArrayList內
Products.Add(New Product(PTitle, PDescUrl, RelProducts, Prices))
Next
'傳回Products ArrayList
Return Products
End Function
End Class

Public Class Product
Private m_Title, m_DescUrl As String
Private m_RelProducts, m_Prices As ArrayList
Public Sub New(ByVal PTitle As String, ByVal PDescUrl As String, ByVal RelProducts As ArrayList, ByVal Prices As ArrayList)
m_Title = PTitle
m_DescUrl = PDescUrl
m_RelProducts = RelProducts
m_Prices = Prices
End Sub

Public ReadOnly Property Title() As String
Get
Return m_Title
End Get
End Property
Public ReadOnly Property DescURL() As String
Get
Return m_DescUrl
End Get
End Property
Public ReadOnly Property RelProducts() As ArrayList
Get
Return m_RelProducts
End Get
End Property
Public ReadOnly Property Prices() As ArrayList
Get
Return m_Prices
End Get
End Property
End Class

在Create方法內撰寫對section剖析的程式碼,section的內容是來自配置檔案內的標記,剖析後將值用來建立Product的實體,再將Products ArrayList一一放入對Product實體的參照,最後將該ArrayList傳回,但在IConfigurationSectionHandler介面內的Create方法的簽名碼傳回的資料型別是Object,是故在呼叫者必需轉換型態為ArrayList。
3、 參考自訂處理器類別
在ASP.NET Web應用程式專案(ProWebConfig)中加入參考,在加入參考對話盒中選擇[專案]頁籤,加入參考[ProProductHandler]專案。
4、 宣告配置區段(Products)

項目下宣告,其section屬性名稱設為Products,而type屬性指定為處理器類別的組件(Assembly)和類別名稱。
5、 取得配置內容與資料呈現
在RootForm.aspx上增加一按鈕[Button1],在屬性視窗中改Text為[GetProductsList],在該Button的Click事件中撰寫下面程式碼:

Dim Products As ArrayList
Dim anProduct As ProProductHandler.Product
Dim i As Integer
Products = CType(System.Configuration.ConfigurationSettings.GetConfig("Products"), ArrayList)
If Not Products Is Nothing Then
For Each anProduct In Products
Response.Output.WriteLine("< a href=""" & anProduct.DescURL & """" & ">" & anProduct.Title & "< /a>")
If Not anProduct.RelProducts Is Nothing Then
For i = 0 To anProduct.RelProducts.Count - 1
Response.Output.WriteLine(anProduct.RelProducts.Item(i) & ":$" & anProduct.Prices.Item(i))
Next
End If
Next
End If

在System.Configuration.ConfigurationSettings.GetConfig("Products")會呼叫處理器類別的Create方法,因簽名碼的關係取回的是Object型態,此處借由型別轉換回真正傳回的ArrayList型態;而後續再取出ArrayList內的Product一一組成我們所要呈現的介面,執行結果呈現如下(圖三)。

(圖三) 取得配置內容的Web資料呈現

結論:
這篇文章是這系列文章中的最後一篇,我們對電腦(machine)、應用程式(application)和安全性(security) 各配置檔案做了簡單的介紹;當然我們特別著重在應用程式配置檔案中怎麼自訂配置區段的部份,一般有二個步驟:先宣告配置區段指定區段名稱和處理器類別,再依宣告名稱設定配置區段的內容。若無特殊需求一般可利用已在電腦配置檔案宣告的appSettings來做區段配置;當然您若要自訂區段名稱則可視自己所需在項目下宣告區段名稱,指定.NET Framework所提供的處理器類別,讓我們的區段結構描述是要以XML Node還提XML Attribute鍵/值成對為主;最後若鍵/值成對無法滿足您配置需求時,我們為各位解說怎麼利用實作IConfigurationSectionHandler介面來撰寫自訂的處理器類別,來剖析處理特殊的配置區段內容。
若各位讀者希望能夠撰寫較佳的處理器類別,對於進一步研究.NET上的XML操作是不可或缺的,畢竟配置檔案是XML Base的,當然各位亦可參考附件的dictionarysectionhandler.cs、ignoresectionhandler.cs、namevaluefilesectionhandler.cs、namevaluesectionhandler.cs、singletagsectionhandler.cs系統提供的處理器類別原始碼亦是以操作XML為主。
參考內容:
MSDN線上說明文件
Configuring Applications in .NET(http://www.c-sharpcorner.com/Code/2002/June/ConfigApp.asp)
Creating Custom Configuration Section Handlers(http://www.dotnetbips.com/displayarticle.aspx?id=127)
Specifying Configuration Settings in Web.config(http://aspnet.4guysfromrolla.com/articles/053102-1.aspx)

沒有留言:

加入書籤: MyShare HemiDemi Baidu Google Bookmarks Yahoo! My Web PChome Del.icio.us Digg technorati furludn bookmark 其他更多書籤

BOOKS:New and Upcoming