(譯者注:本文介紹了.NET中XML Serialization的概念和一個相應的簡單的例子,同時也涉及了很多.NET中比較重要的概念,如Stream,Reflection,服務器端控件的使用等,雖然並沒有很詳細地說明XML Serialization的實際用途,但我們也可以從文章和它的例子中得到很多啟示。本文所帶的例子用VS.Net打開時可能會有問題,所以最好是按照本文的講述自己創建一個例子,以加深理解)
在本文中,我們將一起了解一下XML的序列化(Serialization)。它是這樣一個過程:得到一個對象,把對象轉換為一個XML文檔,並且保存它以供使用,或者把它傳到網絡上其他地方以供使用。在.Net中,XML serialization通過檢查類的屬性是否被標志為read/write來工作。只要有其中一個屬性,該類的值就會被取出並插入到一個XML文檔裡去。反序列化(De-serialization)則是一個相反的過程。
毫無疑問,.NET可以很方便的使用XML。在.NET中,使用XML Serialization需要做的就是把對象轉化為一塊XML,然後把它當作“流”(stream)傳出去。隨著對.NET的了解,你將會發現“流”這個比喻很貼切。比如如果要向磁盤寫一個文件,需要打開一個文件流;也可以通過打開了一個網絡流發送字節到另一台機器上。“流”的方法很簡捷並且可以用在.Net開發中的很多方面,一旦你知道了一種“流”的使用辦法,那麼你就會很容易的掌握其他的使用方法。
.Net Framework中的XML Serialization
當第一次看到XML Serialization的時候,我覺得它看起來很復雜。把一個對象轉換為一個XML塊,需要實例化一個XmlSerializer對象並把要轉換的對象傳給他。同樣,把一個XML塊轉換為一個對象,我們也需要用XmlSerializer,只是這次我們需要傳入一個XML而不是對象。
多數情況下,你不必對要做序列化(serialize)的對象作任何改動。XMLSerializer檢查對象的屬性,並假設對象中任何可以read/write的屬性都應該被包括在序列化過程中。然後它將像一個典型的客戶程序一樣調用這些屬性。
比如如果你的對象實現了一個read/write的屬性叫做Name,那麼XMLSerializer將調用該屬性並把返回值插入到XML塊中。當用XmlSerializer從一個XML塊建立一個對象時,它將取出保存在XML塊中的值並將其設置為對象的屬性值。(這個過程是通過reflection實現的,我們在後面會談到)
作為一個典型的開發人員,當我第一次看到XML Serialization時,我覺得並不是很舒服。因為我覺得這就像個雜牌電腦一樣。我認為它的過程應該是這樣的:比如,XmlSerializer應該調用一個接口中的方法,該方法要求我提供需要插入到XML中的信息。事實上這的確是System.Runtime.Serialization名字空間中的ISerializable接口所做的工作。而實現ISerializable並不麻煩,相反使用XMLSerializer卻是很繁瑣的事。
直到現在,我已經對XML Serialization有了很長時間的了解,我認識到它的功能確實很強大而且很值得去使用。對一個有經驗的開發者來說,不用擔心對其缺少控制,XML serialization為我們提供了一個很快捷的方法可以把對象壓成一個流然後再把他們抽出來。
Reflection
對於沒有接觸過的人來說,你會看到reflection是一個很強大的功能,在這個過程裡,.NET Framework中的任何對象可以被檢查並且可以決定它的屬性,方法和事件。任何.Net中的對象都是從Object類中派生出來的,Object類包含了一個叫做GetType的方法,這個方法返回一個System.Type類型的對象,這個對象包含了一些方法如GetPropertIEs和GetMethods,他們可以用來得到更多的關於對象的信息。
XMLSerializer簡單的調用GetPropertIEs方法返回一個PropertyInfo對象數組,數組中每一個值都描述了對象的一個屬性。如果屬性是read/write的,它就可以被包含在序列化中。
ASPToday中有專門關於reflection的文章,此外如果感興趣的話,你也可以在其他地方找到相關的資料。當然你也可以自己試一下Framework SDK中的ClsVIEw例子。Reflection中最讓人頭疼的地方是emitting功能,它讓你可以在運行時創建一個類然後在你的程序中使用這個類,就好像他們是正常的類一樣。
測
試序列化
為了測試一下我們的序列化,我們需要一個應用程序,其中應該包含一個用來轉化為XML的類,並且可以再轉化回來。我們用VB.NET/ASP.Net來做,首先創建一個新的Visual Basic – Web Application項目,針對本文,項目命名為Serialization,如果看一下代碼,你會發現這會是一個很好的名字
為了顯示結果,我們在項目中創建一個包括一個text area的web form。我們要使用一個叫Book的對象,該對象包括name, ISBN Number以及author列表等屬性。這個text area將用來顯示由XmlSerializer產生的XML。 然後我們還可以修改產生的XML並且通過這個XML創建一個新的對象。(比如我們可以通過Public Beta把書的標題從Beginning E-commerce改成VB .Net Programming)。一旦我們得到了新的對象,我們要用一個簡單的服務器端控件處理一下這個對象並顯示。
創建Form
首先我們需要創建一個form,打開ASPX頁面的Html視圖做以下修改:<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.vb"
Inherits="Serialization.WebForm1"%>
<Html><head>
<meta name="GENERATOR" content="Microsoft Visual Studio .Net 7.0">
<meta name="CODE_LANGUAGE" content="Visual Basic 7.0"></head>
<body>
<form id="WebForm1" method="post" runat="server">
<textarea runat="server" id="XMLarea" cols="60" rows="15"></textarea>
<br>
<input runat="server" type="submit" value="Turn XML into an object!">
</form>
</body></Html>
請注意我們把text area元素的id屬性設置為XMLarea。這將允許我們在VB代碼中操縱該元素。通常我們用Value屬性來得到或者設置元素所包含的文本內容。如果運行頁面,我們可以得到以下結果:
VS.Net的開發環境中有個問題:盡管我們已經把text area加入到頁面中了,但有時候對XMLarea的引用並不會加入到WebForm1類的定義中。如果沒有這個引用,我們將不能使用和處理該字段,因此我們也不能得到或者設置它的值。如果你打開WebForm1.vb的代碼,應該可以看到下面這樣的代碼行Public Class WebForm1
Inherits System.Web.UI.Page
Protected WithEvents XMLarea As System.Web.UI.HtmlControls.HtmlTextArea
如果這一行不在,那麼你自己加上它。
創建Book類
我們要使用的類叫做Book。開始我們先簡單的使用類中的Name和ISBN屬性。這裡沒什麼特殊的,所以創建一個叫做Book的新類。
Imports System
Imports System.Collections
Public Class Book
Private m_Name As String
Private m_ISBN As String
Public Property Name() As String
Get
Return m_Name
End Get
Set
m_Name = Value
End Set
End Property
Public Property ISBN() As String
Get
Return m_ISBN
End Get
Set
m_ISBN = value
End Set
End Property
End Class
處理PreRender
在處理輸出頁面上的窗體前,我們要確定xmlarea字段中包含了XML塊。因此我們需要創建一個Book類的實例,設置Name和ISBN屬性的默認值並調用XMLSerializer來序列化該對象。
當然我們需要先把對XmlSerializer的引用加到我們的項目中來。在Solution Explorer中,右擊Reference並選擇Add Reference。找到System.XML.Serialization.dll,選中點擊OK。
在使用對象前,我們需要在WebForm1.vb的頂部再加上必要的引用:Imports System
Imports System.ComponentModel.Design
Imports System.Data
Imports System.Drawing
Imports System.Web
Imports System.Web.SessionState
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports Microsoft.VisualBasic
Imports System.IO
Imports System.XML.Serialization
在IDE中打開WebForm1.vb,從左上角選擇對象,拖放,實例化WebForm1對象,從右邊的列表中選擇PreRender方法。把下面的代碼加入其中來檢查我們是否能夠從XMLarea中得到值:Public Sub WebForm1_PreRender(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles WebForm1.PreRender
@# if we don@#t already have a value, create a default book...
If XMLarea.Value = "" Then
如果form已經被提交,XMLarea中將有一個值。其中會包含用戶想加入的任何信息。接下來我們創建一個Book對象的實例並且設置屬性值:@# create an instance of a book...
Dim MyBook As New Book()
MyBook.Name = "Beginning E-commerce"
MyBook.ISBN = "1861003986"
接下來我們需要一個System.IO.Tex
tWriter,XMLSerializer會把數據產生給它。一個TextWriter通常用來提供對數據流的訪問,比如一個磁盤文件或者網絡連接。在我們的例子中,我們使用System.IO.TextWriter。這是一個TextWriter對象,表示字符串中已經存在的部分,不論何時新的數據加入都會被連接到已存在數據的末尾。@# create a new string writer...
Dim writer As New StringWriter()
接著我們創建XMLSerializer對象,這需要我們要進行序列化的事物的Type對象了。一旦有了這個,我們要求它來把對象序列化為StringWriter對象。
[TABLE][TR][TD]@# create a serializer...
Dim serializer As New XMLSerializer(MyBook.GetType)
serializer.Serialize(writer, MyBook)
最後我們可以用StringWriter的ToString方法得到XML塊的內容,我們把text area元素的value值設成該字符串:
@# set the value in the form...
XMLarea.Value = writer.ToString
End If
End Sub
如果運行代碼,我們可以看到默認的Book對象所代表的XML Serialization字符串
把XML傳回對象