基本序列化

使一个类可序列化的最简单方式是按如下所示使用 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。只需用 SoapFormatter 代替上面代码中的 BinaryFormatter,并且如前面一样调用 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="https://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP- ENV="https://schemas.xmlsoap.org/soap/envelope/"
  SOAP-ENV:encodingStyle=
  "https://schemas.microsoft.com/soap/encoding/clr/1.0"
  "https://schemas.xmlsoap.org/soap/encoding/"
  xmlns:a1="https://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 属性十分方便,但它具有上面所述的限制。有关何时应将类标记为进行序列化的信息,请参见序列化指南;在对类进行编译后,就不能再向该类添加序列化。

请参见

其他资源

二进制序列化
远程对象
XML 和 SOAP 序列化