CSDN 的序列化

序列化

序列化是将对象状态转换为可保持或传输的形式的过程。序列化的补集是反序列化,后者将流转换为对象。这两个过程一起保证数据易于存储和传输。

NET Framework 提供了两个序列化技术:

  • 二进制序列化保持类型保真,这对于多次调用应用程序时保持对象状态非常有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等。远程处理使用序列化,按值在计算机或应用程序域之间传递对象。
  • XML 序列化只序列化公共属性和字段,并且不保持类型保真。当您希望提供或使用数据而不限制使用该数据的应用程序时,这一点非常有用。由于 XML 是开放式的标准,因此它对于通过 Web 共享数据来说是一个理想选择。SOAP 同样是开放式的标准,这使它也成为一个理想选择。

二进制序列化

可以将序列化定义为一个将对象状态存储到存储介质的过程。在这个过程中,对象的公共字段和私有字段以及类(包括含有该类的程序集)的名称,将转换成字节流,而字节流接着将写入数据流。随后对该对象进行反序列化时,将创建原始对象的准确克隆。

在面向对象的环境中实现序列化机制时,必须多在易用性与灵活性之间做出权衡。很大程度上,这个过程可以自动完成,但前提是您对该过程拥有足够的控制权。例如,如果简单的二进制序列化不足,或者可能有特定原因决定需要对类中的哪些字段进行序列化,可能就会出现这种情况。以下章节说明了随 .NET Framework 一起提供的可靠序列化机制,并强调了根据需要自定义该过程所能使用的一些重要功能。

序列化概念

为什么要使用序列化?两个最重要的原因是将对象状态保存到存储媒体,以便可以在以后阶段重新创建精确副本;以及将对象按值从一个应用程序域发送至另一个应用程序域。例如,序列化用于在 ASP.NET 中保存会话状态,并将对象复制到 Windows 窗体的剪贴板中。它还可用于在远程处理中将对象按值从一个应用程序域传递至另一个应用程序域。

经常有必要将对象的字段值存储至磁盘,以后再检索此数据。尽管不依赖序列化也能很容易地实现这一点,但方法通常麻烦而容易出错,并且需要跟踪对象的层次结构时会逐渐变得更加复杂。假设要编写一个包含数千个对象的大型商务应用程序,并且必须为每个对象编写代码,以便将字段和属性保存至磁盘以及从磁盘进行还原。序列化为实现这一目标提供了方便的机制。

公共语言运行库可管理对象在内存中存储的方式,并通过使用反射提供一种自动序列化机制。当序列化对象时,类的名称、程序集和类实例的所有数据成员被写入存储区。对象经常以成员变量方式将引用存储至其他实例。当序列化类时,序列化引擎跟踪被引用的对象(已序列化),以确保同一对象不会被多次序列化。随 .NET Framework 一起提供的序列化体系结构可自动正确地处理对象图和循环引用。对于对象图的唯一要求是,也必须将已序列化的对象引用的所有对象标记为 Serializable(有关更多信息,请参见基本序列化)。如果未进行标记,序列化程序尝试序列化未标记的对象时将引发异常。

当反序列化已序列化的类时,将重新创建该类,并且将自动还原所有数据成员的值。

[Serializable]

public class MyObject {

  public int n1 = 0;

  public int n2 = 0;

  public String str = null;

}

MyObject obj = new MyObject();

obj.n1 = 1;

obj.n2 = 24;

obj.str = "Some String";

IFormatter formatter = new BinaryFormatter();

Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None);

formatter.Serialize(stream, obj);

stream.Close();

此示例使用二进制格式化程序执行序列化。您只需要创建流的实例以及要使用的格式化程序,然后在该格式化程序上调用 Serialize 方法。要序列化的流和对象将作为参数提供给此调用。尽管未在此示例中明确演示,但类的所有成员变量都将被序列化,即使将变量标记为私有也是如此。在这一方面,二进制序列化与 XMLSerializer 不同,后者只序列化公共字段。有关从二进制序列化排除成员变量的信息,请参见有选择的序列化

IFormatter formatter = new BinaryFormatter();

Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);

MyObject obj = (MyObject) formatter.Deserialize(stream);

stream.Close();

 

// Here's the proof.

Console.WriteLine("n1: {0}", obj.n1);

Console.WriteLine("n2: {0}", obj.n2);

Console.WriteLine("str: {0}", obj.str);

上面使用的 BinaryFormatter 非常有效,并可产生压缩字节流。使用此格式化程序序列化的所有对象也可使用它进行反序列化,这使得它成为对将在 .NET Framework 上反序列化的对象进行序列化的理想工具。需要特别注意的是,反序列化对象时不调用构造函数。这是出于性能原因而对反序列化进行的约束。然而,这违反了运行库对对象编写器制定的某些常用协定,并且将对象标记为可序列化时开发人员应确保了解其后果。

如果要求可移植,请改用 SoapFormatter。只需要将以上代码中的 BinaryFormatter 替换为 SoapFormatter,然后与前面一样调用 Serialize Deserialize。此格式化程序针对以上使用的示例产生下面的输出:

<SOAP-ENV:Envelope

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema"

  xmlns:SOAP- ENC="http://schemas.xmlsoap.org/soap/encoding/"

  xmlns:SOAP- ENV="http://schemas.xmlsoap.org/soap/envelope/"

  SOAP-ENV:encodingStyle=

  "http://schemas.microsoft.com/soap/encoding/clr/1.0"

  "http://schemas.xmlsoap.org/soap/encoding/"

  xmlns:a1="http://schemas.microsoft.com/clr/assem/ToFile">

 

  <SOAP-ENV:Body>

    <a1:MyObject id="ref-1">

      <n1>1</n1>

      <n2>24</n2>

      <str id="ref-3">Some String</str>

    </a1:MyObject>

  </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

需要特别注意的是,无法继承 Serializable 属性。如果从 MyObject 派生新类,新类也必须标记为以上属性,否则将无法序列化。例如,尝试序列化以下类的实例时,将收到 SerializationException,通知您 MyStuff 类型未标记为可序列化。

public class MyStuff : MyObject

{

  public int n3;

}

使用 Serializable 属性非常方便,但有以上所述的限制。有关何时应标记类以进行序列化的信息,请参见序列化准则;在编译类后不能对类进行序列化。

有选择的序列化

类通常包含不应进行序列化的字段。例如,假定类将线程 ID 存储在成员变量中。如果反序列化该类,而在对该类进行序列化时,存储了该 ID 的线程可能不再运行。因此,序列化该值毫无意义。您可以防止对成员变量进行序列化,方法是使用 NonSerialized 属性标记它们,如下所述。

 [Serializable]

public class MyObject

{

  public int n1;

  [NonSerialized] public int n2;

  public String str;

}

如有可能,应使可能包含安全敏感数据的对象不可序列化。如果必须对该对象进行序列化,可将 NonSerialized 属性应用于存储敏感数据的特定字段。如果没有将这些字段排除在序列化之外,应该注意它们存储的数据将向有权序列化的所有代码公开。

序列化准则

由于编译类之后不能使类可序列化,因此设计新的类时应考虑序列化。有些要问的问题是:需要跨应用程序域发送此类吗?此类可用于远程处理吗?用户将对此类进行哪些操作?他们会从需要序列化的我的类派生新类吗?当无法确定时,请将此类标记为可序列化。除非可确定以下任一情况,否则可能最好将所有类标记为可序列化。

  • 类永远不会跨应用程序域。如果不需要序列化并且类需要跨应用程序域,则请从 MarshalByRefObject 派生类。
  • 类存储仅适用于它的当前实例的特殊指针。例如,如果某个类包含非托管内存或文件句柄,则请确保用 NonSerializedAttribute 属性标记这些文件,或者根本不序列化该类。
  • 类数据成员包含敏感信息。在此情况下,建议将类标记为可序列化,但建议用 NonSerializedAttribute 属性标记包含敏感信息的各数据成员。另一个方法是实现 ISerializable 接口并只序列化所需的字段。

请注意将类标记为可序列化的安全含义。类或类构造函数上 CodeAccessPermission Link Demand Inheritance Demand 可以在默认情况下或者由自定义序列化跳过,该序列化可实现对同一 CodeAccessPermission 的相应需求。(有关更多信息,请参见 SecurityAction 枚举)。如果类具有权限的 Link Demand,则运行库只检查直接调用方来验证该权限是否已授予调用方。使用 Microsoft 强名称对 .NET Framework 类库代码进行签名,并始终对它授予完全信任。任何代码都可使用被授予完全信任的代码来跳过链接时的安全检查。例如,在序列化情况下,没有所需序列化权限的恶意代码可调用其中一个完全信任的 .NET Framework 格式化程序(如 BinaryFormatter),并跳过链接时对权限的检查。

XML SOAP 序列化

XML 序列化将对象的公共字段和属性或者方法的参数及返回值转换(序列化)为符合特定 XML 架构定义语言 (XSD) 文档的 XML 流。XML 序列化会生成强类型类,同时将公共属性和字段转换为序列格式(在此情况下为 XML),以便存储或传输。

由于 XML 是开放式的标准,因此可以根据需要由任何应用程序处理 XML 流,而与平台无关。例如,用 ASP.NET 创建的 XML Web services 使用 XmlSerializer 类来创建 XML 流,这些流在整个 Internet 中或在 Intranet 上的 XML Web services 应用程序之间传递数据。相反,反序列化采用这样一个 XML 流并重新构造对象。

XML 序列化还可用于将对象序列化为符合 SOAP 规范的 XML 流。SOAP 是一种基于 XML 的协议,它是专门为使用 XML 来传输过程调用而设计的。

要序列化或反序列化对象,请使用 XmlSerializer 类。要创建待序列化的类,请使用 XML 架构定义工具。

XML 序列化简介

序列化是将对象转换成易于传输的形式的过程。例如,可以序列化对象,并使用 HTTP 通过 Internet 在客户端和服务器之间进行传输。另一方面,反序列化在流中重新构建对象。

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

注意:

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

XML 序列化中的中心类是 XmlSerializer 类,该类中最重要的方法是 Serialize Deserialize 方法。XmlSerializer 创建 C# 文件并将其编译为 .dll 文件,以执行此序列化。在 .NET Framework 2.0 中,XML 序列化程序生成器工具 (Sgen.exe) 旨在预先生成这些序列化程序集,以便与应用程序一起部署并改善启动性能。XmlSerializer 生成的 XML 流符合万维网联合会 (www.w3.org) XML 架构定义语言 (XSD) 1.0 建议书。而且,生成的数据类型符合文档“XML 架构第 2 部分:数据类型”(XML Schema Part 2: Datatypes)

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

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

属性可控制 XmlSerializer 类生成的 XML 流,从而允许您设置 XML 流的 XML 命名空间、元素名称、属性名称等。有关这些属性及其如何控制 XML 序列化的更多信息,请参见使用属性控制 XML 序列化。有关用于控制生成的 XML 的那些属性所组成的表,请参见用来控制 XML 序列化的属性

XmlSerializer 类可以进一步序列化对象并生成编码的 SOAP XML 流。生成的 XML 符合万维网联合会文档简单对象访问协议 (SOAP) 1.1”(Simple Object Access Protocol (SOAP) 1.1) 的第 5 节。有关此过程的更多信息,请参见如何:将对象序列化为 SOAP 编码的 XML 。有关控制生成的 XML 的属性所组成的表,请参见用来控制编码的 SOAP 序列化的属性

XmlSerializer 类生成由 XML Web services 创建并传递给 XML Web services SOAP 消息。要控制 SOAP 消息,可以将属性应用于在 XML Web services 文件 (.asmx) 中找到的类、返回值、参数和字段。由于 XML Web services 可以使用文本或编码的 SOAP 样式,因此既可以使用用来控制 XML 序列化的属性中列出的属性,也可以使用用来控制编码的 SOAP 序列化的属性中列出的属性。有关使用属性来控制由 XML Web services 生成的 XML 的更多信息,请参见使用 XML Web services 进行 XML 序列化。有关 SOAP XML Web services 的更多信息,请参见Customizing SOAP Messages

XmlSerializer 应用程序的安全注意事项

创建应用程序来使用 XmlSerializer 时,应注意以下几项及其含义:

  • XmlSerializer TEMP 环境变量命名的目录中创建 C# (.cs) 文件并将其编译为 .dll 文件;这些 DLL 文件将进行序列化。

注意:

可预先生成这些序列化程序集,并使用 SGen.exe 工具对它们进行签名。这不适用于 Web 服务的服务器。也就是说,这只适用于客户端用法和手动序列化。

  • 代码和 DLL 在创建和编译时易受恶意进程破坏。当使用的计算机运行 Microsoft Windows NT 4.0 或更高版本时,可能有两个或多个用户共享 TEMP 目录。如果两个帐户的安全权限不同,且权限较高的帐户使用 XmlSerializer 运行应用程序,则共享 TEMP 目录是危险的。在这种情况下,一个用户可能因替换已编译的 .cs .dll 文件而违反计算机的安全性。要消除这一问题,应始终确保计算机上的每个帐户具有各自的配置文件。默认情况下,TEMP 环境变量为每个帐户指向不同的目录。
  • 如果恶意用户将连续的 XML 数据流发送至 Web 服务器(拒绝服务攻击),则 XmlSerializer 会持续处理数据,直至计算机资源不足。

如果您使用的计算机运行了 Internet 信息服务 (IIS),并且您的应用程序在 IIS 内运行,则可消除这种攻击。IIS 提供了一种网关,这种网关不处理长度超过设定量(默认值为 4 KB)的流。如果创建的应用程序不使用 IIS 并且使用 XmlSerializer 进行反序列化,则您应当实现类似的网关,以防止拒绝服务攻击。

  • XmlSerializer 使用提供给它的任何类型序列化数据并运行任何代码。

恶意对象造成威胁的方式有两种。它可以运行恶意代码,也可以将恶意代码插入 XmlSerializer 所创建的 C# 文件。在第一种情况下,如果恶意对象试图运行破坏性的过程,代码访问安全有助于防止发生任何损坏。在第二种情况下,理论上讲恶意对象有可能以某种方式将代码插入 XmlSerializer 所创建的 C# 文件。尽管这一问题已得到彻底检查并且认为不可能发生这种攻击,但还是应当采取防范措施,一定不要使用未知和不受信任的类型来序列化数据。

  • 已序列化的敏感数据可能容易受到攻击。

XmlSerializer 序列化数据后,数据可以存储在 XML 文件或其他数据存储区中。如果数据存储区可供其他进程使用或者可在 Intranet Internet 上看见,则数据可能被盗和恶意使用。例如,如果您创建一个应用程序来序列化包含信用卡号码的订单,则数据是高度敏感的。为防止被盗和恶意使用,应始终保护您的数据存储区并采取步骤保持其私密性。

简单类的序列化

下面的代码示例显示具有公共字段的基类。

public class OrderForm

{

    public DateTime OrderDate;

}

此类的实例序列化后可能如下所示。

<OrderForm>

    <OrderDate>12/12/01</OrderDate>

</OrderForm>

可序列化的项

可使用 XmLSerializer 类对以下项进行序列化:

  • 公共类的公共读/写属性和字段。
  • 实现 ICollection IEnumerable 的类。

注意:

仅序列化集合,不序列化公共属性。

  • XmlElement 对象。
  • XmlNode 对象。
  • DataSet 对象。

有关序列化或反序列化对象的更多信息,请参见如何:序列化对象如何:反序列化对象

使用 XML 序列化的优点

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

例如,XmlSerializer 可让您:

  • 指定字段或属性 (Property) 是否应编码为属性 (Attribute) 或元素。
  • 指定要使用的 XML 命名空间。
  • 指定字段或属性 (Property) 名称不恰当时的元素或属性 (Attribute) 名称。

XML 序列化的另一个优点是,只要生成的 XML 流符合给定的架构,就对开发的应用程序没有任何约束。假设有一个架构,它用于描述书籍。它提供有书名、作者、出版商和 ISBN 号元素。您可以开发一个应用程序来以任何想要的方式(例如以书籍订单或书籍库存方式)处理 XML 数据。在任一种情况下,唯一的要求是 XML 流符合指定的 XML 架构定义语言 (XSD) 架构。

XML 序列化注意事项

使用 XmlSerializer 类时,应注意以下事项:

  • Sgen.exe 工具特别设计为生成序列化程序集,以获得最佳性能。
  • 序列化数据只包含数据本身和类的结构。类型标识和程序集信息不包括在内。
  • 只能序列化公共属性和字段。属性必须具有公共访问器(get set 方法)。如果必须序列化非公共数据,请使用 BinaryFormatter 类而不是 XML 序列化。
  • 类必须具有默认构造函数才能被 XmlSerializer 序列化。
  • 方法不能被序列化。
  • 如果可实现 IEnumerable ICollection 的类满足特定要求,则 XmlSerializer 可以以不同方式处理这些类,如下所述。

实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法。Add 方法的参数必须与从 IEnumerator.Current 属性返回的类型一致(多态),该属性是从 GetEnumerator 方法返回的。

除了 IEnumerable 之外,实现 ICollection(如 CollectionBase)的类还必须有一个采用整数的公共 Item 索引属性(在 C# 中为索引器),而且必须有一个 integer 类型的公共 Count 属性。传递给 Add 方法的参数的类型必须与从 Item 属性返回的类型相同,或者为此类型的基之一。

对于实现 ICollection 的类,可从已编制索引的 Item 属性检索要序列化的值,而不是通过调用 GetEnumerator。此外,除了返回另一个集合类(实现 ICollection 的类)的公共字段外,公共字段和属性不会被序列化。有关示例,请参见 XML 序列化示例

XSD 数据类型映射

万维网联合会 (www.w3.org) 文档“XML 架构第 2 部分:数据类型”(XML Schema Part 2: Datatypes) 指定 XML 架构定义语言 (XSD) 架构所允许的简单数据类型。对于其中的许多数据类型(如 int decimal),.NET Framework 中有相应的数据类型。然而,某些 XML 数据类型在 .NET Framework 中没有相应的数据类型(如 NMTOKEN 数据类型)。在这种情况下,如果使用 XML 架构定义工具 (XML 架构定义工具 (Xsd.exe)) 从架构中生成类,相应的属性 (Attribute) 会应用于字符串类型的成员,其 DataType 属性 (Property) 会设置为 XML 数据类型名称。例如,如果架构包含 XML 数据类型为 NMTOKEN 且名为“MyToken”的元素,则生成的类可能包含下例所示的成员。

Visual Basic

<XmlElement(DataType:="NMTOKEN")> _

Public MyToken As String

 

[XmlElement(DataType = "NMTOKEN")]

public string MyToken;

同样,如果要创建的类必须符合特定的 XML 架构 (XSD),则应当应用相应的属性 (Attribute) 并将其 DataType 属性 (Property) 设置为所需的 XML 数据类型名称。

有关类型映射的完整列表,请参见以下任一属性 (Attribute) 类的 DataType 属性 (Property)

如何:序列化对象

·         要序列化对象,首先应创建要序列化的对象,然后设置其公共属性和字段。为此,必须确定 XML 流的传输格式,即它是作为流还是作为文件进行存储。例如,如果 XML 流必须以永久形式保存,则应创建 FileStream 对象。

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);

myWriter.Close();

如何:反序列化对象

当您反序列化对象时,传输格式确定您将创建流还是文件对象。确定了传输格式之后,就可以根据需要调用 Serialize Deserialize 方法。

反序列化对象

1.        使用要反序列化的对象的类型构造 XmlSerializer

2.        调用 Deserialize 方法以生成该对象的副本。在反序列化时,必须将返回的对象强制转换为原始对象的类型,如下面的示例中所示,该示例将该对象反序列化为文件(尽管也可以将该对象反序列化为流)。

MySerializableClass myObject;

// Construct an instance of the XmlSerializer with the type

// of object that is being deserialized.

XmlSerializer mySerializer =

new XmlSerializer(typeof(MySerializableClass));

// To read the file, create a FileStream.

FileStream myFileStream =

new FileStream("myFileName.xml", FileMode.Open);

// Call the Deserialize method and cast to the object type.

myObject = (MySerializableClass)

mySerializer.Deserialize(myFileStream)

如何:重写编码的 SOAP XML 序列化

将对象的 XML 序列化重写为 SOAP 消息的过程类似于重写标准 XML 序列化的过程。有关重写标准 XML 序列化的信息,请参见如何:指定 XML 流的替代元素名称

将对象的序列化重写为 SOAP 消息

1.        创建 SoapAttributeOverrides 类的实例。

2.        为正在序列化的每个类成员创建 SoapAttributes

3.        对正在序列化的成员适当创建影响 XML 序列化的一个或多个属性的实例。有关更多信息,请参见用来控制编码的 SOAP 序列化的属性

4.        SoapAttributes 的相应属性 (Property) 设置为在步骤 3 中创建的属性 (Attribute)

5.        SoapAttributes 添加至 SoapAttributeOverrides

6.        使用 SoapAttributeOverrides 创建 XmlTypeMapping。使用 SoapReflectionImporterImportTypeMapping 方法。

7.        使用 XmlTypeMapping 创建 XmlSerializer

8.        序列化或反序列化对象。

示例

下面的代码示例以两种方式序列化文件:第一种方式,不重写 XmlSerializer 类的行为;第二种方式,重写该行为。示例包含带有几个成员的名为 Group 的类。已将各个属性(如 SoapElementAttribute)应用于类成员。当已使用 SerializeOriginal 方法序列化该类时,属性会控制 SOAP 消息的内容。调用 SerializeOverride 方法后,XmlSerializer 的行为会被重写,方法是创建各个属性 (Attribute) 并根据需要将 SoapAttributes 的属性 (Property) 设置为这些属性 (Attribute)

using System;

using System.IO;

using System.Xml;

using System.Xml.Serialization;

using System.Xml.Schema;

 

public class Group

{

    [SoapAttribute (Namespace = "http://www.cpandl.com")]

    public string GroupName;

   

    [SoapAttribute(DataType = "base64Binary")]

    public Byte [] GroupNumber;

 

    [SoapAttribute(DataType = "date", AttributeName = "CreationDate")]

    public DateTime Today;

    [SoapElement(DataType = "nonNegativeInteger", ElementName = "PosInt")]

    public string PostitiveInt;

    // This is ignored when serialized unless it is overridden.

    [SoapIgnore]

    public bool IgnoreThis;

 

    public GroupType Grouptype;

   

    [SoapInclude(typeof(Car))]

    public Vehicle myCar(string licNumber)

    {

        Vehicle v;

        if(licNumber == "")

            {

                v = new Car();

            v.licenseNumber = "!!!!!!";

        }

        else

        {

            v = new Car();

            v.licenseNumber = licNumber;

        }

        return v;

    }

}

 

public abstract class Vehicle

{

    public string licenseNumber;

    public DateTime makeDate;

}

 

public class Car: Vehicle

{

}

 

public enum GroupType

{

    // These enums can be overridden.

    small,

    large

}

   

public class Run

{

    public static void Main()

    {

        Run test = new Run();

        test.SerializeOriginal("SoapOriginal.xml");

        test.SerializeOverride("SoapOverrides.xml");

        test.DeserializeOriginal("SoapOriginal.xml");

        test.DeserializeOverride("SoapOverrides.xml");

   

    }

    public void SerializeOriginal(string filename)

    {

        // Creates an instance of the XmlSerializer class.

        XmlTypeMapping myMapping =

        (new SoapReflectionImporter().ImportTypeMapping(

        typeof(Group)));

        XmlSerializer mySerializer = 

        new XmlSerializer(myMapping);

 

        // Writing the file requires a TextWriter.

        TextWriter writer = new StreamWriter(filename);

 

        // Creates an instance of the class that will be serialized.

        Group myGroup = new Group();

 

        // Sets the object properties.

        myGroup.GroupName = ".NET";

 

        Byte [] hexByte = new Byte[2]{Convert.ToByte(100),

        Convert.ToByte(50)};

        myGroup.GroupNumber = hexByte;

 

        DateTime myDate = new DateTime(2002,5,2);

        myGroup.Today = myDate;

 

        myGroup.PostitiveInt= "10000";

        myGroup.IgnoreThis=true;

        myGroup.Grouptype= GroupType.small;

        Car thisCar =(Car)  myGroup.myCar("1234566");

 

        // Prints the license number just to prove the car was created.

        Console.WriteLine("License#: " + thisCar.licenseNumber + "/n");

 

        // Serializes the class and closes the TextWriter.

        mySerializer.Serialize(writer, myGroup);

        writer.Close();

    }

 

    public void SerializeOverride(string filename)

    {

        // Creates an instance of the XmlSerializer class

        // that overrides the serialization.

        XmlSerializer overRideSerializer = CreateOverrideSerializer();

        // Writing the file requires a TextWriter.

        TextWriter writer = new StreamWriter(filename);

        // Creates an instance of the class that will be serialized.

        Group myGroup = new Group();

        // Sets the object properties.

        myGroup.GroupName = ".NET";

 

        Byte [] hexByte = new Byte[2]{Convert.ToByte(100),

        Convert.ToByte(50)};

        myGroup.GroupNumber = hexByte;

 

        DateTime myDate = new DateTime(2002,5,2);

        myGroup.Today = myDate;

 

 

        myGroup.PostitiveInt= "10000";

        myGroup.IgnoreThis=true;

        myGroup.Grouptype= GroupType.small;

        Car thisCar =(Car)  myGroup.myCar("1234566");

 

        // Serializes the class and closes the TextWriter.

        overRideSerializer.Serialize(writer, myGroup);

         writer.Close();

    }

 

    public void DeserializeOriginal(string filename)

    {

        // Creates an instance of the XmlSerializer class.

        XmlTypeMapping myMapping =

        (new SoapReflectionImporter().ImportTypeMapping(

        typeof(Group)));

        XmlSerializer mySerializer = 

        new XmlSerializer(myMapping);

 

        TextReader reader = new StreamReader(filename);

 

        // Deserializes and casts the object.

        Group myGroup;

        myGroup = (Group) mySerializer.Deserialize(reader);

 

        Console.WriteLine(myGroup.GroupName);

        Console.WriteLine(myGroup.GroupNumber[0]);

        Console.WriteLine(myGroup.GroupNumber[1]);

        Console.WriteLine(myGroup.Today);

        Console.WriteLine(myGroup.PostitiveInt);

        Console.WriteLine(myGroup.IgnoreThis);

        Console.WriteLine();

    }

 

    public void DeserializeOverride(string filename)

    {

        // Creates an instance of the XmlSerializer class.

        XmlSerializer overRideSerializer = CreateOverrideSerializer();

        // Reading the file requires a TextReader.

        TextReader reader = new StreamReader(filename);

 

        // Deserializes and casts the object.

        Group myGroup;

        myGroup = (Group) overRideSerializer.Deserialize(reader);

 

        Console.WriteLine(myGroup.GroupName);

        Console.WriteLine(myGroup.GroupNumber[0]);

        Console.WriteLine(myGroup.GroupNumber[1]);

        Console.WriteLine(myGroup.Today);

        Console.WriteLine(myGroup.PostitiveInt);

        Console.WriteLine(myGroup.IgnoreThis);

    }

 

    private XmlSerializer CreateOverrideSerializer()

    {

        SoapAttributeOverrides mySoapAttributeOverrides =

        new SoapAttributeOverrides();

        SoapAttributes soapAtts = new SoapAttributes();

 

        SoapElementAttribute mySoapElement = new SoapElementAttribute();

        mySoapElement.ElementName = "xxxx";

        soapAtts.SoapElement = mySoapElement;

        mySoapAttributeOverrides.Add(typeof(Group), "PostitiveInt",

        soapAtts);

 

        // Overrides the IgnoreThis property.

        SoapIgnoreAttribute myIgnore = new SoapIgnoreAttribute();

        soapAtts = new SoapAttributes();

        soapAtts.SoapIgnore = false;     

        mySoapAttributeOverrides.Add(typeof(Group), "IgnoreThis",

        soapAtts);

 

        // Overrides the GroupType enumeration.

        soapAtts = new SoapAttributes();

        SoapEnumAttribute xSoapEnum = new SoapEnumAttribute();

        xSoapEnum.Name = "Over1000";

        soapAtts.SoapEnum = xSoapEnum;

 

        // Adds the SoapAttributes to the

        // mySoapAttributeOverridesrides.

        mySoapAttributeOverrides.Add(typeof(GroupType), "large",

        soapAtts);

 

        // Creates a second enumeration and adds it.

        soapAtts = new SoapAttributes();

        xSoapEnum = new SoapEnumAttribute();

        xSoapEnum.Name = "ZeroTo1000";

        soapAtts.SoapEnum = xSoapEnum;

        mySoapAttributeOverrides.Add(typeof(GroupType), "small",

        soapAtts);

 

        // Overrides the Group type.

        soapAtts = new SoapAttributes();

        SoapTypeAttribute soapType = new SoapTypeAttribute();

        soapType.TypeName = "Team";

        soapAtts.SoapType = soapType;

        mySoapAttributeOverrides.Add(typeof(Group),soapAtts);

 

        // Creates an XmlTypeMapping that is used to create an instance

        // of the XmlSerializer class. Then returns the XmlSerializer.

        XmlTypeMapping myMapping = (new SoapReflectionImporter(

        mySoapAttributeOverrides)).ImportTypeMapping(typeof(Group));

   

        XmlSerializer ser = new XmlSerializer(myMapping);

        return ser;

    }

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值