.NET Framework 开发员指南  

序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。

XML 序列化仅将对象的公共字段和属性值序列化为 XML 流。XML 序列化不包括类型信息。例如,如果您有一个存在于 Library 命名空间中的 Book 对象,将不能保证它将会被反序列化为同一类型的对象。

注意   XML 序列化不转换方法、索引器、私有字段或只读属性(只读集合除外)。若要序列化对象的所有字段和属性(公共的和私有的),请使用BinaryFormatter,而不要使用 XML 序列化。

XML 序列化中最主要的类是 XmlSerializer 类,它的最重要的方法是 Serialize 和 Deserialize 方法。XmlSerializer 生成的 XML 流符合万维网联合会 (www.w3.org) XML 架构定义语言 (XSD) 1.0 的建议。另外,生成的数据类型符合标题为“XML Schema Part 2: Datatypes”(XML 架构第二部分:数据类型)的文档。

对象中的数据是用编程语言构造(如类、字段、属性、基元类型、数组,甚至 XmlElement 或 XmlAttribute 对象形式的嵌入 XML)来描述的。您可以创建自己的用属性批注的类,或者使用 XML 架构定义工具生成基于现有 XML 架构的类。

如果您有 XML 架构,就可运行 XML 架构定义工具生成一组强类型化为架构并用属性批注的类。当序列化这样的类的实例时,生成的 XML 符合 XML 架构。使用这样的类,就可针对容易操作的对象模型进行编程,同时确保生成的 XML 符合 XML 架构。这是使用 .NET Framework 中的其他类(如 XmlReader 和 XmlWriter 类)分析和写 XML 流的一种替换方法。(有关使用这些类的更多信息,请参见使用 .NET Framework 中的 XML。)这些类使您可以分析任何 XML 流。与此相反,当需要 XML 流符合已知的 XML 架构时,请使用 XmlSerializer

属性控制由 XmlSerializer 类生成的 XML 流,使您可以设置 XML 流的 XML 命名空间、元素名、属性名等。有关这些属性和它们如何控制 XML 序列化的更多信息,请参见使用属性控制 XML 序列化。若想获得一个列示对所生成的 XML 起控制作用的那些属性的表,请参见控制 XML 序列化的属性

XmlSerializer 类可进一步序列化对象并生成编码的 SOAP XML 流。生成的 XML 符合标题为“Simple Object Access Protocol (SOAP) 1.1”的万维网联合会文档的第 5 节。有关此过程的更多信息,请参见用 XML 序列化生成 SOAP 消息。有关控制生成的 XML 的属性表,请参见控制编码的 SOAP 序列化的属性

XmlSerializer 类生成由 XML Web services 创建和传递给 XML Web services 的 SOAP 消息。若要控制 SOAP 消息,可将属性应用于 XML Web services 文件 (.asmx) 中的类、返回值、参数和字段。您可以同时使用在“控制 XML 序列化的属性”中列出的属性和在“控制编码的 SOAP 序列化的属性”中列出的属性,因为 XML Web services 可以使用文本样式,也可以使用编码的 SOAP 样式。有关使用属性控制 XML Web services 所生成的 XML 的更多信息,请参见 XML Web services 的 XML 序列化。有关 SOAP 和 XML Web services 的更多信息,请参见自定义 SOAP 消息

保护 XmlSerializer 应用程序

在创建使用 XmlSerializer 的应用程序时,您应当了解以下几点以及它们的影响:

  • XmlSerializer 创建 C# 文件 (.cs 文件),并将其编译成 .dll 文件,这些 .dll 文件位于由 TEMP 环境变量指定的目录中;这些 DLL 文件将发生序列化。

    代码和 DLL 在创建和进行编译时,易于遭受恶意进程的攻击。如果所使用的计算机运行的是 Microsoft Windows NT 4.0 或更高版本,则有可能会有两个或更多用户共享临时目录。如果同时存在以下两种情况,则共享临时目录是有危险性的:(1) 两个帐户有不同的安全特权;(2) 具有较高特权的帐户运行一个使用 XmlSerializer 的应用程序。在这种情况下,某一用户可以替换所编译的 .cs 或 .dll 文件,由此破坏计算机的安全性。为了避免发生这一问题,请始终确保计算机上的每一帐户都有自己的配置文件。如果能够保证这一点的话,默认情况下,TEMP 环境变量就会为不同的帐户指定不同的目录。

  • 如果一名恶意用户向 Web 服务器发送持续的 XML 数据流(拒绝服务攻击),XmlSerializer 会一直处理这一数据,直到计算机资源不够用才停止。

    如果您所使用的计算机运行 Internet 信息服务 (IIS),并且您的应用程序是在 IIS 下运行,就可以避免这类攻击。IIS 带有一个控制门,用于禁止处理大于设定数量(默认值是 4 KB)的数据流。如果您所创建的应用程序不使用 IIS,同时该应用程序使用 XmlSerializer 进行反序列化,则应该实现一个类似的控制门,以阻止拒绝服务攻击。

  • XmlSerializer 将使用给予它的任何类型,对数据进行序列化,并运行任何代码。

    恶意对象施加威胁的方式有两种。一种是运行恶意代码,另一种是将恶意代码插入到由 XmlSerializer 创建的 C# 文件中。在第一种情况下,如果恶意对象试图运行破坏性过程,代码访问安全性将帮助防止发生任何破坏。在第二种情况下,在理论上,恶意对象有可能会以某种方式将代码插入到由 XmlSerializer 创建的 C# 文件中。尽管对这一问题已进行了彻底的检验,而且这类攻击被认为是不可能的,但您还是应该小心一些,一定不要序列化那些不可信的未知类型的数据。

  • 已序列化的重要数据可能易于遭到攻击。

    XmlSerializer 对数据进行了序列化之后,数据可以被存储为 XML 文件,或存储在其他数据存储区。如果其他进程可以访问到您的数据存储区,或是可以在 Intranet 或 Internet 上看到该数据存储区,数据就可能被窃取,并被恶意使用。例如,如果您创建了一个应用程序,对包含信用卡号码的订单进行序列化,这一数据就非常重要。为了防止发生这一问题,请始终保护您的数据存储区,并对数据采取保密措施。

简单类的序列化

下面的示例显示一个具有公共字段的简单类:

  1. [Visual Basic]Public Class OrderForm Public OrderDate As DateTimeEnd Class[C#]public class OrderForm{ public DateTime OrderDate;}

当将此类的实例序列化时,该实例可能类似于下面的代码:

  1. <OrderForm> <OrderDate>12/12/01</OrderDate></OrderForm>

有关序列化的更多示例,请参见 XML 序列化的示例

可以序列化的项

使用 XmLSerializer 类,可将下列项序列化。

  • 公共类的公共读/写属性和字段
  • 实现 ICollection 或 IEnumerable 的类。(注意只有集合会被序列化,而公共属性却不会。)
  • XmlElement 对象。
  • XmlNode 对象。
  • DataSet 对象。

序列化和反序列化对象

若要序列化对象,首先创建要序列化的对象并设置它的公共属性和字段。为此,必须确定要用以存储 XML 流的传输格式(或者作为流,或者作为文件)。例如,如果 XML 流必须以永久形式保存,则创建 FileStream 对象。当您反序列化对象时,传输格式确定您将创建流还是文件对象。确定了传输格式之后,就可以根据需要调用 Serialize 或Deserialize 方法。

序列化对象

  1. 创建对象并设置它的公共字段和属性。
  2. 使用该对象的类型构造 XmlSerializer。有关更多信息,请参见 XmlSerializer 类构造函数。
  3. 调用 Serialize 方法以生成对象的公共属性和字段的 XML 流表示形式或文件表示形式。下面的示例创建一个文件。
    1. [Visual Basic]Dim myObject As MySerializableClass = New MySerializableClass()' Insert code to set properties and fields of the object.Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(MySerializableClass))' To write to a file, create a StreamWriter object.Dim myWriter As StreamWriter = New StreamWriter("myFileName.xml")mySerializer.Serialize(myWriter, myObject)[C#]MySerializableClass myObject = new MySerializableClass();// Insert code to set properties and fields of the object.XmlSerializer mySerializer = new XmlSerializer(typeof(MySerializableClass));// To write to a file, create a StreamWriter object.StreamWriter myWriter = new StreamWriter("myFileName.xml");mySerializer.Serialize(myWriter, myObject);

反序列化对象

  1. 使用要反序列化的对象的类型构造 XmlSerializer
  2. 调用 Deserialize 方法以产生该对象的副本。在反序列化时,必须将返回的对象强制转换为原始对象的类型,如下面的示例中所示。下面的示例将该对象反序列化为文件,尽管它也可以被反序列化为流。
    1. [Visual Basic]Dim myObject As MySerializableClass' Constructs an instance of the XmlSerializer with the type' of object that is being deserialized.Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(MySerializableClass))' To read the file, creates a FileStream.Dim myFileStream As FileStream = _New FileStream("myFileName.xml", FileMode.Open)' Calls the Deserialize method and casts to the object type.myObject = CType( _mySerializer.Deserialize(myFileStream), MySerializableClass)[C#]MySerializableClass myObject;// Constructs an instance of the XmlSerializer with the type// of object that is being deserialized.XmlSerializer mySerializer = new XmlSerializer(typeof(MySerializableClass));// To read the file, creates a FileStream.FileStream myFileStream = new FileStream("myFileName.xml", FileMode.Open);// Calls the Deserialize method and casts to the object type.myObject = (MySerializableClass) mySerializer.Deserialize(myFileStream)

有关 XML 序列化的更多示例,请参见 XML 序列化的示例

使用 XML 序列化的好处

XmlSerializer 类在您将对象序列化为 XML 时为您提供完整而灵活的控制。如果您正在创建 XML Web services,则可以将控制序列化的属性应用于类和成员以确保 XML 输出符合特定的架构。

例如,XmlSerializer 使您能够:

  • 指定应将字段或属性编码为特性还是元素。
  • 指定要使用的 XML 命名空间。
  • 如果字段或属性名不合适,则指定元素或特性的名称。

XML 序列化的另一个好处是:只要生成的 XML 流符合给定的架构,则对于所开发的应用程序就没有约束。假定有这样一个用于描述图书的架构,它具有标题、作者、出版商和 ISBN 编号元素。您可以开发一个以您希望的任何方式(例如,作为图书订单,或作为图书清单)处理 XML 数据的应用程序。在任一种情况下,唯一的要求是 XML 流应当符合指定的 XML 架构定义语言 (XSD) 架构。

XML 序列化注意事项

使用 XmlSerializer 类时,应考虑下列情况:

  • 序列化数据只包含数据本身以及类的结构。不包括类型标识和程序集信息。
  • 只能序列化公共属性和字段。如果需要序列化非公共数据,请使用 BinaryFormatter 类而不是 XML 序列化。
  • 类必须有一个将由 XmlSerializer 序列化的默认构造函数。
  • 不能序列化方法。
  • XmlSerializer 可以以不同方式处理实现 IEnumerable 或 ICollection 的类(条件是这些类满足某些要求)。实现 IEnumerable 的类必须实现带单个参数的公共 Add 方法。Add 方法的参数必须与从 GetEnumerator 方法返回的 IEnumerator.Current 属性所返回的类型一致(多态)。除实现 IEnumerable 外还实现 ICollection 的类(如CollectionBase)必须有一个取整数的公共 Item 索引属性(在 C# 中为索引器),并且它必须有一个整数类型的公共 Count 属性。传递给 Add 方法的参数必须与从 Item 属性返回的类型相同或与该类型的某个基的类型相同。对于实现 ICollection 的类,要序列化的值将从索引 Item 属性检索,而不是通过调用 GetEnumerator 来检索。另外请注意,除返回另一个集合类(实现 ICollection 的集合类)的公共字段之外,将不序列化公共字段和属性。有关示例,请参见 XML 序列化的示例

XSD 数据类型映射

标题为“XML Schema Part 2: Datatypes”的万维网联合会 (www.W3.org) 文档指定在 XML 架构定义语言 (XSD) 架构中允许使用的简单数据类型。对于这些数据类型中的许多类型(例如,int 和 decimal),在 .NET Framework 中都有对应的数据类型。但是,某些 XML 数据类型在 .NET Framework 中没有对应的数据类型(例如,NMTOKEN数据类型)。在这样的情况下,如果使用 XML 架构定义工具 (Xsd.exe) 从架构生成类,就会将适当的特性应用于字符串类型的成员,并会将其 DataType 属性设置为 XML 数据类型名称。例如,如果架构包含一个数据类型为 XML 数据类型 NMTOKEN 的、名为“MyToken”的元素,则生成的类可能包含以下示例中的成员。

  1. [Visual Basic]<XmlElement(DataType:="NMTOKEN")>Public MyToken As String[C#][XmlElement(DataType = "NMTOKEN")]public string MyToken;

与此类似,如果创建一个必须符合特定 XML 架构 (XSD) 的类,应当应用适当的特性并将它的 DataType 属性设置为所需的 XML 数据类型名称。

有关类型映射的完整列表,请参见下列任意一个特性类的 DataType 属性:SoapAttributeAttributeSoapElementAttributeXmlArrayItemAttributeXmlAttributeAttributeXmlElementAttribute 或 XmlRootAttribute

C#: .net序列化及反序列化 [XmlElement(“节点名称”)] [XmlAttribute(“节点属性”)] (下篇)的更多相关文章

  1. C#: .net序列化及反序列化 [XmlElement(“节点名称”)] [XmlAttribute(“节点属性”)] (上篇)

    .net序列化及反序列化 序列化是指一个对象的实例可以被保存,保存成一个二进制串,当然,一旦被保存成二进制串,那么也可以保存成文本串了.比如,一个计数器,数值为2,我们可以用字符串"2&qu ...

  2. 【转】JavaScript获取节点类型、节点名称和节点值

    DOM节点信息包括节点类型(nodeType).节点名称(nodeName)和节点值(nodeValue). 节点类型 DOM节点中,每个节点都拥有不同的类型.W3C规范中常用的 DOM节点类型有以下 ...

  3. JavaScript判断对象类型及节点类型、节点名称和节点值

    一.JavaScript判断对象类型 1.可以使用typeof函数判断对象类型 function checkObject1(){ var str="str"; console.lo ...

  4. tensorflow 根据节点名称获取节点

    ckpt_file = os.path.join(self.args.bert_dir, 'model.ckpt-6123') # 获取图的reader reader = self.tf_instan ...

  5. C#: .net序列化及反序列化 [XmlElement(“节点名称”)]

    .net序列化及反序列化 序列化是指一个对象的实例可以被保存,保存成一个二进制串,当然,一旦被保存成二进制串,那么也可以保存成文本串了.比如,一个计数器,数值为2,我们可以用字符串“2”表示.如果有个 ...

  6. 重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化

    [源码下载] 重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化 作者:webabcd 介绍重新想象 Windows 8 Store Apps ...

  7. SpringBoot系列: Json的序列化和反序列化

    ============================= 控制 json 序列化/反序列化=============================1. @JsonIgnoreProperties的 ...

  8. C#对象序列化与反序列化zz

      C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍........................ ...

  9. XML序列化和反序列化

    上篇总结了下JSON的序列化和反序列化,博园中大牛给了很多牛叉的评论,学习了不少. 不过在上篇中忘了把json序列化和反序列化的另外一种方式写上去了,这里做个简单的补充: Json篇:http://w ...

随机推荐

  1. 敲出的第一个python程序

    学习python第二天,终于照猫画虎编辑出第一个程序.程序要求如下: 1.输入用户名.密码 2.认证成功后显示欢迎信息 3.输错三次后锁定 源代码如下: username = 'jackson'pas ...

  2. 用python的turtle作图(二)动画吃豆人

    本文是用python的turtle作图的第二篇,通过这个例子可以了解动画的原理,用python自带的turtle库制作一些小动画. 1.问题描述 在上一篇"用python的turtle作图( ...

  3. suse 12 二进制部署 Kubernetets 1.19.7 - 第10章 - 部署kube-proxy组件

    文章目录 1.10.部署kube-proxy 1.10.0.创建kube-proxy证书 1.10.1.生成kube-proxy证书和秘钥 1.10.2.创建kube-proxy的kubeconfig ...

  4. shell脚本的“奇迹暖暖“之行 -- printf彩色输出

    printf \n" \n代表换行 "\e[1;30m \e[0m" 深灰 "\e[1;31m \e[0m" 红色 "\e[1;32m \e ...

  5. 手撸一个springsecurity,了解一下security原理

    手撸一个springsecurity,了解一下security原理 转载自:www.javaman.cn 手撸一个springsecurity,了解一下security原理 今天手撸一个简易版本的sp ...

  6. Dapr 中文社区汇总

    Dapr 于 2019 年在微软创建.随着时间的推移,许多社区成员加入该项目并做出贡献,扩展并帮助它在 2021 年 2 月达到了稳定的 1.0 版本.2021年3 月提交给 CNCF,在2021年1 ...

  7. 实例详解 Java 死锁与破解死锁

    锁和被保护资源之间的关系 我们把一段需要互斥执行的代码称为临界区.线程在进入临界区之前,首先尝试加锁 lock(),如果成功,则进入临界区,此时我们称这个线程持有锁:否则呢就等待,直到持有锁的线程解锁 ...

  8. 深入理解Java类加载机制,再也不用死记硬背了

    谈谈"会"的三个层次 在<说透分布式事务>中,我举例里说明了会与会的差别.对一门语言的学习,这里谈谈我理解的"会"的三个层次: 第一层:了解这门语言 ...

  9. HttpClient的使用(get、post请求)

    添加pom依赖 <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <d ...

  10. msf生成后门实战漫游内网

    前言:当我们在渗透当中首先拿到webshell权限,进一步提权渗透,获得内网的主机,假设在这里我们获取了具有双网卡的web服务器,我们的目的是通过这台web服务器,进行内网漫游,获取内网中其他主机的系 ...