XML 序列化 (Serialization) 是將物件公用屬性和欄位轉換為儲存或傳輸所用的序列格式 (此處即為 XML) 的程。還原序列化 (Deserialization) 是從 XML 輸出將物件重新建立成它的原始狀態。您可以將序列化視為在資料流或緩衝區中儲存物件狀態的方式。例如,ASP.NET 是使用 XmlSerializer 類別來編碼 XML Web Service 訊息。
您物件中的資料是用程式語言來描述的,該程式語言會建構如類別、欄位、屬性、基本型別 (Primitive Type)、陣列,甚至是以 XmlElement 或 XmlAttribute 物件為格式的內嵌 XML。您可以選擇以屬性註解建立自己的類別,或使用 XML 結構描述定義工具 (Xsd.exe) 來產生依據現有 XML 結構描述定義 (XSD) 文件的類別。如果有 XML 結構描述,您可以執行 Xsd.exe 來產生類別集,這些類別集是結構描述的強型別 (Strongly Typed),而且在序列化時以屬性註解來符合結構描述。
為了在物件之間傳輸資料,XML 需要從程式語言建構至 XML 結構描述的對應,以及從 XML 結構描述至程式語言建構的對應。XmlSerializer 和相關工具 (如 Xsd.exe),在設計階段和執行階段都提供了連接這兩項技術的橋樑。在設計階段,請使用 Xsd.exe 從自訂類別產生 XML 結構描述文件 (.xsd),或從指定的結構描述產生類別。不論哪一種情況,類別都會加註自訂屬性,指示 XmlSerializer 如何在 XML 結構描述系統和 Common Language Runtime 之間對應。在執行階段,可以將類別的執行個體序列化成符合指定之結構描述的 XML 文件。同樣地,這些 XML 文件可以還原序列化成執行階段物件。請注意,XML 結構描述是選擇性的,在設計階段或執行階段並不需要。
控制產生的 XML
若要控制產生的 XML,您可以將一些特別的屬性套用至類別和成員。例如,若要指定不同的 XML 項目名稱,可將 XmlElementAttribute 套用至公用欄位或屬性,並且設定 ElementName 屬性。如需類似屬性的完整清單,請參閱 控制 XML 序列化的屬性。您也可以實作 IXmlSerializable 介面,以控制 XML 輸出。
如果產生的 XML 必須符合全球資訊網協會 (www.w3.org) 文件<Simple Object Access Protocol (SOAP) 1.1>的第 5 節,您必須使用 XmlTypeMapping 來建構 XmlSerializer。若要進一步控制編碼的 SOAP XML,請使用 控制編碼 SOAP 序列化的屬性 中所列的屬性。
使用 XmlSerializer,您可以利用強型別類別來運作,而且還保有 XML 的彈性。在強型別類別中使用 XmlElement、XmlAttribute 或 XmlNode 型別的欄位或屬性,可以直接將 XML 文件的部分讀取至 XML 物件中。
如果使用可延伸 XML 結構描述,您也可以使用 XmlAnyElementAttribute 和 XmlAnyAttributeAttribute 屬性來序列化和還原序列化原始結構描述中找不到的項目和屬性。若要使用該物件,請將 XmlAnyElementAttribute 套用到傳回 XmlElement 物件陣列的欄位,或將 XmlAnyAttributeAttribute 套用到傳回 XmlAttribute 物件陣列的欄位。
如果屬性或欄位傳回複雜物件 (例如陣列或類別執行個體),XmlSerializer 會將它轉換為主要 XML 文件中的巢狀項目。例如,下列程式碼中的第一個類別,會傳回第二個類別的執行個體。
Public Class MyClass
Public MyObjectProperty As MyObject
End Class
Public Class MyObject
Public ObjectName As String
End Class
public class MyClass
{
public MyObject MyObjectProperty;
}
public class MyObject
{
public string ObjectName;
}
已序列化的 XML 輸出看起來會像這樣:
<MyClass>
<MyObjectProperty>
<ObjectName>My String</ObjectName>
</MyObjectProperty>
</MyClass>
如果結構描述包含選擇性的項目 (minOccurs = '0'),或如果結構描述包含預設值,您就有兩種選擇。一個選項是使用 System.ComponentModel..::.DefaultValueAttribute,指定預設值,如下列程式碼所示。
Public Class PurchaseOrder
<System.ComponentModel.DefaultValueAttribute ("2002")> _
Public Year As String
End Class
public class PurchaseOrder
{
[System.ComponentModel.DefaultValueAttribute ("2002")]
public string Year;
}
另一種選擇是使用特別的模式以建立 XmlSerializer 可辨識的布林 (Boolean) 欄位,並套用 XmlIgnoreAttribute 至該欄位。以 propertyNameSpecified 的格式建立其模式。例如,如果有名為 "MyFirstName" 的欄位,您也會建立名為 "MyFirstNameSpecified" 的欄位,指示 XmlSerializer 是否要產生名為 "MyFirstName" 的 XML 項目。這在下列範例中顯示。
Public Class OptionalOrder
' This field's value should not be serialized
' if it is uninitialized.
Public FirstOrder As String
' Use the XmlIgnoreAttribute to ignore the
' special field named "FirstOrderSpecified".
<System.Xml.Serialization.XmlIgnoreAttribute> _
Public FirstOrderSpecified As Boolean
End Class
public class OptionalOrder
{
// This field should not be serialized
// if it is uninitialized.
public string FirstOrder;
// Use the XmlIgnoreAttribute to ignore the
// special field named "FirstOrderSpecified".
[System.Xml.Serialization.XmlIgnoreAttribute]
public bool FirstOrderSpecified;
}
覆寫預設的序列化
動態產生的組件
為了增加效能,XML 序列化基礎結構會動態產生組件,以序列化和還原序列化指定的型別。基礎結構會尋找並重新使用那些組件。只有在使用下列建構函式時,才會出現這個行為:
XmlSerializer..::.XmlSerializer(Type)
XmlSerializer..::.XmlSerializer(Type, String)
如果您使用任何其他建構函式,則會產生相同組件的多個版本且無法卸載,導致記憶體遺漏和效能不佳。最簡單的解決方案就是使用先前提及的兩個建構函式。否則,您必須在 Hashtable 中快取組件,如下列範例所示。
Hashtable serializers = new Hashtable();
// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);
// Implement a method named GenerateKey that creates unique keys
// for each instance of the XmlSerializer. The code should take
// into account all parameters passed to the XmlSerializer
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);
// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null)
{
ser = new XmlSerializer(typeof(MyClass), myRoot);
// Cache the serializer.
serializers[key] = ser;
}
else
{
// Use the serializer to serialize, or deserialize.
}
Dim serializers As New Hashtable()
' Use the constructor that takes a type and XmlRootAttribute.
Dim s As New XmlSerializer(GetType([MyClass]), myRoot)
' Implement a method named GenerateKey that creates unique keys
' for each instance of the XmlSerializer. The code should take
' into account all parameters passed to the XmlSerializer
' constructor.
Dim key As Object = GenerateKey(GetType([MyClass]), myRoot)
' Check the local cache for a matching serializer.
Dim ser As XmlSerializer = CType(serializers(key), XmlSerializer)
If ser Is Nothing Then
ser = New XmlSerializer(GetType([MyClass]), myRoot)
' Cache the serializer.
serializers(key) = ser
Else
' Use the serializer to serialize, or deserialize.
End If
ArrayList 和泛型清單的序列化
XmlSerializer 無法序列化或還原序列化下列項目:
序列化 Unsigned Long 的列舉型別
如果下列條件成立,就無法產生 XmlSerializer 以序列化列舉型別:列舉型別為 Unsigned Long (C# 中為 ulong),而且列舉型別包含值大於 9,223,372,036,854,775,807 的任何成員。例如,下列項目無法序列化。
public enum LargeNumbers: ulong
{
a = 9223372036854775808
}
// At runtime, the following code will fail.
xmlSerializer mySerializer=new XmlSerializer(typeof(LargeNumbers));以 Obsolete 屬性標示的物件不會再序列化
在 .NET Framework 3.5 中,XmlSerializer 類別不會再序列化標示為 [Obsolete] 的物件。