System.Xml.Serialization.XmlSerializer 类

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

XML 序列化是将对象的公共属性和字段转换为存储或传输的串行格式(在本例中为 XML)的过程。 反序列化将 XML 输出中的对象还原到其原始状态。 可以将序列化视为将对象状态保存到流或缓冲区的方法。 例如,ASP.NET 使用该 XmlSerializer 类对 XML Web 服务消息进行编码。

使用编程语言结构(如类、字段、属性、基本类型、数组,甚至通过 XmlElementXmlAttribute 对象形式嵌入的 XML)描述对象中的数据。 可以选择创建自己的类、使用属性批注或使用 XML 架构定义工具(Xsd.exe) 基于现有 XML 架构定义(XSD)文档生成类。 如果您有一个 XML 架构,可以运行 Xsd.exe 命令来生成一组与该架构强类型匹配的类,并在序列化时用属性进行注释以遵循该架构。

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

控制生成的 XML

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

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

通过使用XmlSerializer,您可以充分利用强类型类的优势,同时仍然享有 XML 的灵活性。 使用强类型类中类型为 XmlElementXmlAttributeXmlNode 的字段或属性,可以直接将 XML 文档的某些部分读取到 XML 对象中。

如果使用可扩展 XML 架构,还可以使用 XmlAnyElementAttributeXmlAnyAttributeAttribute 属性对原始架构中未找到的元素或属性进行序列化和反序列化。 若要使用这些对象,请向返回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 识别,并将 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 方法的参数的类型必须与从 Current 返回的值的 GetEnumerator 属性返回的类型或该类型的基之一相同。 除了 ICollection 之外,实现 CollectionBase(如 IEnumerable)的类还必须有一个采用整数的公共 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如果满足以下条件,则无法实例化以序列化枚举:枚举的类型为无符号长(ulong以 C# 为单位),并且枚举包含值大于 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] 的对象。