序列化是将对象转换为可以轻松传输的形式的过程。 例如,可以使用客户端和服务器之间的 HTTP 序列化对象并通过 Internet 传输对象。 另一方面,反序列化在流中重新构建对象。
XML 序列化仅将对象的公共字段和属性值序列化为 XML 流。 XML 序列化不包括类型信息。 例如,如果 Library 命名空间中存在 Book 对象,则不能保证它被反序列化为同一类型的对象。
注释
XML 序列化不会转换方法、索引器、专用字段或只读属性(只读集合除外)。 若要序列化对象的所有字段和属性(公共和私有),请使用 DataContractSerializer 来代替 XML 序列化。
XML 序列化中的中心类是 XmlSerializer 类,此类中最重要的方法是 Serialize 和 Deserialize 方法。 创建 XmlSerializer C# 文件并将其编译为 .dll 文件以执行此序列化。 XML 序列化程序生成器工具(Sgen.exe)旨在提前生成这些序列化程序集,以便与应用程序一起部署,并提高启动性能。 XmlSerializer 生成的 XML 流符合万维网联盟 (W3C) XML 架构定义语言 (XSD) 1.0 建议。 此外,生成的数据类型符合标题为“XML 架构第 2 部分:数据类型”的文档。
使用编程语言构造(如类、字段、属性、基元类型、数组,甚至以 XmlElement 或 XmlAttribute 对象的形式嵌入 XML)描述对象中的数据。 可以选择创建自己的类、使用属性批注或使用 XML 架构定义工具基于现有 XML 架构生成类。
如果你有 XML 架构,则可以运行 XML 架构定义工具,以生成一组与架构严格类型匹配的类,并使用属性进行标注。 序列化此类的实例时,生成的 XML 遵循 XML 架构。 通过提供这样的类,您可以针对易于操作的对象模型进行编程,同时确保生成的 XML 符合 XML 架构。 这是使用 .NET 中的其他类(如 XmlReader 和 XmlWriter 类)分析和写入 XML 流的替代方法。 有关详细信息,请参阅 XML 文档和数据。 这些类允许分析任何 XML 流。 相比之下,当 XML 流应符合已知的 XML 架构时,请使用 XmlSerializer 。
属性控制 XmlSerializer 类生成的 XML 流,使你可以设置 XML 流的 XML 命名空间、元素名称、属性名称等。 有关这些属性以及如何控制 XML 序列化的详细信息,请参阅 使用属性控制 XML 序列化。 有关用于控制生成的 XML 的属性的表,请参阅 控制 XML 序列化的属性。
XmlSerializer 类可以进一步序列化对象并生成编码的 SOAP XML 流。 生成的 XML 遵循名为“简单对象访问协议(SOAP)1.1”的万维网联盟文档的第 5 节。有关此过程的详细信息,请参阅 如何:将对象序列化为 SOAP-Encoded XML 流。 有关控制生成的 XML 的属性的表,请参阅 控制编码的 SOAP 序列化的属性。
XmlSerializer 类生成由 XML Web 服务创建并传递给 XML Web 服务的 SOAP 消息。 若要控制 SOAP 消息,可以将属性应用于 XML Web 服务文件(.asmx)中找到的类、返回值、参数和字段。 可以使用“控制 XML 序列化的属性”和“控制编码的 SOAP 序列化的属性”中列出的属性,因为 XML Web 服务可以使用文本或编码的 SOAP 样式。 有关使用属性控制 XML Web 服务生成的 XML 的详细信息,请参阅 使用 XML Web Services 进行 XML 序列化。 有关 SOAP 和 XML Web 服务的详细信息,请参阅 自定义 SOAP 消息格式。
XmlSerializer 应用程序的安全注意事项
创建使用 XmlSerializer 的应用程序时,请注意以下项及其含义:
XmlSerializer 创建 C# (.cs) 文件,并将其编译为 TEMP 环境变量命名的目录中 .dll 文件;序列化与这些 DLL 一起发生。
注释
可以使用 SGen.exe 工具提前生成和签名这些序列化程序集。 这不适用于 Web 服务的服务器。 换句话说,它仅用于客户端使用和手动序列化。
创建和编译时,代码和 DLL 容易受到恶意进程的攻击。 两个或更多用户可能共享 TEMP 目录。 如果两个帐户具有不同的安全特权,并且高特权帐户使用 XmlSerializer 运行应用程序,则共享 TEMP 目录很危险。 在这种情况下,一个用户可以通过替换已编译的.cs或 .dll 文件来破坏计算机的安全性。 要消除这一问题,应始终确保计算机上的每个帐户具有各自的配置文件。 默认情况下,TEMP 环境变量指向每个帐户的不同目录。
如果恶意用户将连续的 XML 数据流发送到 Web 服务器(拒绝服务攻击),则 XmlSerializer 会继续处理数据,直到计算机在资源上运行不足。
如果使用运行 Internet Information Services(IIS)的计算机,并且应用程序在 IIS 中运行,则会消除此类攻击。 IIS 具有一个门,该门不会处理超过一定数量的流(默认值为 4 KB)。 如果您创建的应用程序不使用 IIS 并且使用 XmlSerializer 进行反序列化,则应实现类似的机制来防止拒绝服务攻击。
XmlSerializer 序列化数据并使用提供的任何类型执行代码。
恶意对象存在威胁有两种方法。 它可以运行恶意代码,也可以将恶意代码注入 XmlSerializer 创建的 C# 文件中。 第二种情况是,恶意对象可能会以某种方式将代码注入 XmlSerializer 创建的 C# 文件中。 尽管此问题已经被彻底研究过,并且这种攻击被认为不太可能发生,但仍然应采取措施,绝不要序列化具有未知和不受信任类型的数据。
序列化的敏感数据可能很脆弱。
XmlSerializer 序列化数据后,可以存储为 XML 文件或其他数据存储。 如果数据存储可用于其他进程,或者在 Intranet 或 Internet 上可见,则数据可能会被盗并被恶意使用。 例如,如果创建一个应用程序来序列化包含信用卡号的订单,则数据高度敏感。 为了帮助防止这种情况,请始终保护数据的存储,并采取措施使其保持私密。
简单类的序列化
下面的代码示例演示具有公共字段的基本类。
Public Class OrderForm
Public OrderDate As DateTime
End Class
public class OrderForm
{
public DateTime OrderDate;
}
当此类的一个实例被序列化时,它可能看起来如下所示。
<OrderForm>
<OrderDate>12/12/01</OrderDate>
</OrderForm>
有关序列化的更多示例,请参阅 XML 序列化示例。
可序列化的项
可以使用 XmlSerializer 类序列化以下项:
公共类的公共读/写属性和字段。
实现 ICollection 或 IEnumerable 的类。
注释
仅序列化集合,不序列化公共属性。
XmlElement 对象。
XmlNode 对象。
数据集 对象。
有关序列化或反序列化对象的详细信息,请参阅 How to: Serialize an Object and How to: Deserialize an Object.
使用 XML 序列化的优点
将对象序列化为 XML 时, XmlSerializer 类提供完整的灵活控件。 如果要创建 XML Web 服务,可以将控制序列化的属性应用于类和成员,以确保 XML 输出符合特定架构。
例如, XmlSerializer 使你可以:
指定字段或属性是否应编码为属性或元素。
指定要使用的 XML 命名空间。
如果字段或属性名称不合适,请指定元素或属性的名称。
XML 序列化的另一个优点是,只要生成的 XML 流符合给定架构,就对所开发的应用程序没有约束。 假设一个用于描述书籍的架构。 它具有标题、作者、发布者和 ISBN 数字元素。 可以开发一个应用程序,以任何所需方式处理 XML 数据,例如,作为书籍顺序或书籍清单。 在任一情况下,唯一的要求是 XML 流符合指定的 XML 架构定义语言 (XSD) 架构。
XML 序列化注意事项
使用 XmlSerializer 类时,应考虑以下事项:
Sgen.exe 工具设计为生成序列化程序集以实现最佳性能。
序列化的数据仅包含数据本身和类的结构。 类型标识和程序集信息不包含在内。
只能序列化公共属性和字段。 属性必须具有公共访问器(获取和设置方法)。 如果必须序列化非公共数据,请使用 DataContractSerializer 类而不是 XML 序列化。
类必须具有可由 XmlSerializer 序列化的无参数构造函数。
方法不能被序列化。
如果满足某些要求,XmlSerializer 可以处理以不同的方式实现 IEnumerable 或 ICollection 的类,如下所示。
实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法。 Add 方法的参数必须与从 GetEnumerator 方法返回的 IEnumerator.Current 属性返回的类型保持一致(多态)。
除 IEnumerable(如 CollectionBase)外实现 ICollection 的类必须具有采用整数的公共项索引属性(C# 中的索引器),并且它必须具有类型为整数的公共 Count 属性。 传递给 Add 方法的参数的类型必须与从 Item 属性返回的类型或该类型的基数之一相同。
对于实现 ICollection 的类,将从索引 项 属性(而不是调用 GetEnumerator)检索要序列化的值。 此外,公共字段和属性不会序列化,但返回另一个集合类的公共字段除外(一个实现 ICollection)。 有关示例,请参阅 XML 序列化示例。
XSD 数据类型映射
标题为 XML 架构第 2 部分的 W3C 文档:数据类型指定 XML 架构定义语言 (XSD) 架构中允许的简单数据类型。 对于其中的许多(例如 int 和 decimal),.NET 中有一个相应的数据类型。 但是,某些 XML 数据类型没有相应的 .NET 数据类型,例如 NMTOKEN 数据类型。 在这种情况下,如果使用 XML 架构定义工具(XML 架构定义工具(Xsd.exe)从架构生成类,则相应的属性将应用于字符串类型的成员,并且其 DataType 属性设置为 XML 数据类型名称。 例如,如果架构包含具有 XML 数据类型 NMTOKEN 的名为“MyToken”的元素,则生成的类可能包含一个成员,如以下示例所示。
<XmlElement(DataType:="NMTOKEN")> _
Public MyToken As String
[XmlElement(DataType = "NMTOKEN")]
public string MyToken;
同样,如果要创建必须符合特定 XML 架构(XSD)的类,则应应用相应的属性并将其 DataType 属性设置为所需的 XML 数据类型名称。
有关类型映射的完整列表,请参阅以下任一属性类的 DataType 属性: