System.Xml.Serialization.XmlSerializer 类

本文提供了此 API 参考文档的补充说明。

XML 序列化是将对象的公共属性和字段转换为序列格式(这里是指 XML)以便存储或传输的过程。 反序列化则是从 XML 输出中重新创建原始状态的对象。 可将序列化视为一种将对象状态保存到流或缓冲区的方法。 例如,ASP.NET 使用 XmlSerializer 类对 XML Web 服务消息进行编码。

对象中的数据是用编程语言构造来描述的,如类、字段、属性、基元类型、数组,甚至 XmlElementXmlAttribute 对象形式的嵌入 XML。 可以创建自己的用特性批注的类,也可以使用 XML 架构定义工具 (Xsd.exe) 基于现有 XML 架构定义文档生成这些类。 如果有 XML 架构,可通过运行 Xsd.exe 生成一组类,将这组类的类型强制为此架构,并用特性进行批注,以便在进行序列化时附加到此架构。

要在对象和 XML 之间传输数据,需要有从编程语言构造到 XML 架构以及从 XML 架构到编程语言构造的映射。 XmlSerializer 和相关工具(如 Xsd.exe)同时在设计时和运行时为这两种技术提供了关联的纽带。 在设计时,使用 Xsd.exe 从自定义类生成 XML 架构文档 (.xsd),或从给定架构生成类。 在两种情况下,均使用自定义特性对类进行批注,以指示 XmlSerializer 如何在 XML 架构系统与公共语言运行时之间进行映射。 在运行时,可将类的实例序列化为遵循给定架构的 XML 文档。 同样,可将这些 XML 文档反序列化为运行时对象。 注意,XML 架构是选择性使用的,在设计时或运行时不是必需的。

控制生成的 XML

若要控制生成的 XML,可将特殊特性应用于类和成员。 例如,若要指定不同的 XML 元素名称,可向公共字段或属性应用一个 XmlElementAttribute,并设置 ElementName 属性。 有关类似特性的完整列表,请参阅控制 XML 序列化的特性。 还可通过实现 IXmlSerializable 接口控制 XML 输出。

如果生成的 XML 必须符合万维网联合会文档简单对象访问协议 (SOAP) 1.1 第 5 节的内容,则必须使用 XmlTypeMapping 构造 XmlSerializer。 要进一步控制编码的 SOAP XML,请使用控制编码的 SOAP 序列化的特性中列出的特性。

借助 XmlSerializer,可利用强类型化的类,同时仍具有 XML 的灵活性。 在强类型化的类中使用 XmlElementXmlAttributeXmlNode 类型的字段或属性,可直接将 XML 文档中的部分内容读取到 XML 对象中。

如果使用可扩展 XML 架构,还可使用 XmlAnyElementAttributeXmlAnyAttributeAttribute 特性对原始架构中没有的元素或特性进行序列化和反序列化。 若要使用这些对象,可向返回 XmlElement 对象数组的字段应用 XmlAnyElementAttribute,或向返回 XmlAttribute 对象数组的字段应用 XmlAnyAttributeAttribute

如果属性或字段返回一个复杂对象(如数组或类实例),则 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 可识别的布尔字段,并将 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;
}

替代默认序列化

还可通过创建相应特性之一并将其添加到 XmlAttributes 类的实例来替代任意一组对象及其字段和属性的序列化。 以这种方式重写序列化有两个用途:首先,可以控制和扩充 DLL 中找到的对象序列化(即使无权访问源);其次,可以创建一组可序列化类,但以多种方式进行对象序列化。 有关详细信息,请参阅 XmlAttributeOverrides 类和如何:控制派生类的序列化

要序列化对象,可调用 Serialize 方法。 要反序列化对象,可调用 Deserialize 方法。

要向 XML 文档添加 XML 命名空间,请参阅 XmlSerializerNamespaces

注意

XmlSerializer 提供对实现 IEnumerableICollection 的类的特殊处理。 实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法。 Add 方法的参数的类型必须与从 GetEnumerator 返回的值的 Current 属性返回的类型或该类型的基之一相同。 除了 IEnumerable 之外,实现 ICollection(如 CollectionBase)的类还必须有一个采用整数的公共 Item 索引属性(在 C# 中为索引器),而且必须有一个整数类型的公共 Count 属性。 Add 方法的参数的类型必须与从 Item 属性返回的类型相同,或者为此类型的基之一。 对于实现 ICollection 的类,可从已编制索引的 Item 属性检索要序列化的值,而不是通过调用 GetEnumerator

要反序列化一个对象,需要有写入临时目录(由 TEMP 环境变量定义)的权限。

动态生成的程序集

为提高性能,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;
}

// 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
End If

' Use the serializer to serialize or deserialize.

ArrayList 和泛型列表的序列化

XmlSerializer 无法序列化或反序列化以下内容:

无符号 Long 枚举的序列化

如果为以下情况,则无法将 XmlSerializer 实例化以序列化某个枚举:枚举的类型为无符号 long (C# 中的 ulong),且枚举包含值大于 9,223,372,036,854,775,807 的成员。 例如,无法序列化以下内容。

public enum LargeNumbers: ulong
{
    a = 9223372036854775808
}
// At run time, the following code will fail.
xmlSerializer mySerializer=new XmlSerializer(typeof(LargeNumbers));

过时类型

XmlSerializer 类不序列化标记为 [Obsolete]..