序列化是將一個對象儲存到儲存介質上或者將對象進行轉換使之能夠在網路上傳送的行為。在一個對象被序列化之後,你會想要將它還原序列化,也就是將資料重新轉換為可用的對象的行為。這種類型的功能被用在一個對象必須被從一個上下文封送到另一個內容相關的時候,例如當對象跨越App域的時候。另外一個例子是Web服務——對象在伺服器上被序列化,通過網路被(封送或)發送到的用戶端,然後被還原序列化成有用的對象。
從二進位到XML,.NET架構為開發人員提供了很多序列化選項,甚至允許開發人員建立自己的序列化常式。在本文中,我將著重討論XML的序列化,並告訴你如何利用這一內建的功能。
XML序列化
.NET架構提供的一種形式的序列化是XML序列化。在這種類型的序列化裡,對象狀態被以XML格式儲存。這使得被序列化的對象能夠被不同的系統取得並修改,甚至是那些不是用.NET編寫的系統。另外一個優勢是被序列化的對象對於人來說是可讀和可寫的——因此更新對象的方式莫過於開啟寫字板更改其值。
XML序列化常常被來遠端控制項目和Web服務項目裡,雖然你可能會在別的地方發現它,比如DataSet封送。在與Xpath查詢和Predicate方法一起使用的時候,XML序列化能夠被用來實現物件導向的資料庫——我會在今後的文章裡談這方面的內容。
使用XML序列化
在.NET架構裡利用內建的XML序列化方法相對較為容易。你只需要熟悉一些類和屬性就可以開始使用簡單的XML序列化了:
System.Xml.Serialization命名空間:含有使用XML序列化所需要的類和功能。這個命名空間應該被放在使用XML序列化的類的頂部的一個“using”命令裡。
XmlSerializer類:提供將對象序列化和還原序列化的功能。
XmlIgnore屬性:告訴XmlSerializer類跳過你不希望序列化的成員。
這個列表只不過讓你對序列化有一個初步的瞭解。還有更多的對象可以供你在使用XML序列化的時候使用。
列表A是將Customer對象序列化的一個簡單例子。這個Customer對象在下載檔案的應用程式範例裡被定義。
列表A
Customer customer = newCustomer();
customer.FirstName = "Zach";
customer.LastName = "Smith";
XmlSerializer serializer = newXmlSerializer(typeof(Customer));
StringWriter writer = newStringWriter();
serializer.Serialize(writer, customer);
Console.WriteLine(writer.ToString());
正如你看到的,XML序列化是一個很簡單的過程。我們只需要建立一個需要被序列化的對象,建立用於這種類型對象的XmlSerializer,並調用XmlSerializer.Serialize。被序列化的對象然後被寫到提供的Stream裡——在本文中是一個叫做“writer”的StringWriter。
如果你看看被序列化的對象,你會注意到它很容易讀懂。下面就是被序列化的Customer對象的內容:
<?xml version="1.0" encoding="utf-16"?>
<Customer xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Orders />
<LastName>Smith</LastName>
<FirstName>Zach</FirstName>
</Customer>
在這裡,你會看到Customer對象的屬性被序列化,也就是Order對象的列表。如果你將這個輸出與Customer類的定義比較一下,你會注意到“Income”屬性沒有被列出來。這是因為Income屬性本身還帶有一個XmlIgnore屬性,它會讓XML序列化庫在序列化的時候跳過Income屬性。在序列化過程中跳過屬性的一個副作用是這個屬性不會被還原序列化,所以會在還原序列化的時候總是帶有預設的值。
Orders節點是空的,因為這個客戶沒有下訂單。但是如果我們將含有訂單的Customer對象序列化,那麼我們就會得到類似下面的輸出:
<?xml version="1.0" encoding="utf-16"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Orders>
<Order>
<Total>34.56</Total>
</Order>
<Order>
<Total>156.56</Total>
</Order>
</Orders>
<LastName>Smith</LastName>
<FirstName>Zach</FirstName>
</Customer>
要注意每個訂單對象都被單獨序列化並放在被序列化的Customer對象的Orders節點裡。如果你想要還原序列化這個Customer對象,那麼相關聯的Order對象也會被還原序列化。
註:要被序列化或者還原序列化的每個對象都必須有一個空的預設建構函式。如果對象不實現一個空的建構函式,那麼就會引發異常。
還原序列化對象
將對象還原序列化就和將它們序列化一樣簡單。下面的代碼(列表B)顯示了如何將還原序列化儲存在檔案裡的對象:
列表B
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
FileStream file = File.OpenRead(fileToWrite);
Customer customer = (Customer)serializer.Deserialize(file);
file.Close();
上面這段代碼與前面的序列化代碼的唯一不同之處在於我們在這裡調用了XmlSerializer.Deserialize。這個方法會返回一個對象,我們然後就必須轉到將要使用的物件類型上。
其他用法
在某些情況下,通過實現XML序列化來儲存和檢索設定檔案是很有用的。例如,你可以只用建立一個含有所需屬性的類並將它序列化到磁碟上,而不需要編寫一個自訂的XML分析常式來尋找和分析設定檔案。這還允許你在需要的時候對檔案進行手動編輯,讓你不需要自己編寫任何XML分析代碼。這種方式可以用於任何類型的資訊,應用程式可能需要儲存從一個執行到另一個執行的這種類型的資訊。
正如我先前所說的,將XML序列化與Predicate方法(被編譯的搜尋)、Xpath(特別搜尋),以及XmlDocument(提供器)對象一起使用,你可以建立一個物件導向的資料庫,這是完全可行的。
發揮XML序列化的優勢
既然你已經熟悉XML序列化了,那麼我希望你能夠在自己的項目裡找到它的用武之地。從我個人來講,我通過對複雜的應用程式設定使用XML序列化節省了大量的時間,這還不算上我應用程式的其他一些模組。