序列化和反序列化
对象在内存中以引用的方式相互联结,构成一个复杂的对象数。但是,在外部的设备中,却是以一定的序列保存的,比如,图片文件是以一个有规律的字节序列进行保存的,文本文件是通过字符序列进行保存。所以,内存中的对象如果需要保存到使用序列方式存储的设备在,必须要进行信息的重组,以序列的方式进行描述,才能完成这个任务。这个工作就称为序列化。
反序列化就是从序列中重新构建内存中对象的过程。
例如,下面定义的是一个Person类。
[Serializable]
public class Person
{
public int Age { get; private set; }
public string Name { get; private set; }
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
当我们创建一个Person类哦对象实例alice之后,在内存中将会有如下的存储结构:
Person alice = new Person("alice", 20);
对象在内存中的表示形式如图所示:

在C++中,程序员需要参与到序列化和反序列的过程中,在 .NET 中,通过反射,已经可以不再需要程序员参与,非常简单地实现对象的序列化和反序列化。
在System.Runtime.Serialization 命名空间中,定义了 .NET 中进行序列化和反序列所需要的类和接口。其中接口IFormatter定义了序列化器。
public interface IFormatter
主要方法Serialize完成对象的序列化工作,将对象序列化之后写入到流中。
public void Serialize (
Stream serializationStream,
Object graph
)
Deserialize从流中获取信息,还原为内存中的对象。
public Object Deserialize (
Stream serializationStream
)
在.NET类库中,命名空间 System.Runtime.Serialization.Formatters.Binary 提供了一个二进制的序列化器 Binary。
[ComVisibleAttribute(true)]
public sealed class BinaryFormatter : IRemotingFormatter, IFormatter
使用BinaryFormatter可以非常方便地将alice对象序列化为一个字节序列。
在序列化的方法中,需要提供一个字节流以保持序列化的结果。为了方便,这里使用MemoryStream将序列化的结果保存在内存中以便使用。
Person alice = new Person("alice", 20);
BinaryFormatter formatter = new BinaryFormatter();
System.IO.MemoryStream ms = new System.IO.MemoryStream();
formatter.Serialize(ms, alice);
byte[] content = ms.ToArray();
Response.Write(BitConverter.ToString(content));
我们可以将这些字节通过一个用于读取字节流提供基于流的访问,然后借助于反序列化方法重新在内存中构建一个新的Person对象,这个对象显然不是原来的Person对象,但是,表示的数据都是相同的,所以,从数据的角度来说,我们可以认为还原了原来的对象。
System.IO.MemoryStream ms2 = new System.IO.MemoryStream(content);
Person alice2 = formatter.Deserialize(ms2) as Person;
Response.Write("<br/>"+alice2.Name+"<br/>"+alice2.Age);
序列化控制
刚才我们将对象序列化为二进制表示形式,这样的序列化被称为二进制序列化。那么,是不是任何对象都可以进行二进制序列化呢?如果不是的话,什么样的类可以被这样进行二进制序列化呢?
注意,上面定义的Person类,被标注了一个表情。
[Serializable]
这个标签的定义如下(在使用中,后缀Attribute可以省略)。
public abstract class Attribute : _Attribute
这个标签也可以被应用在类的成员上,不过,在默认情况下,类中的素有私有和共有的成员在序列化的过程中都将被序列化。也就是说,对于支持序列化的类来说,默认情况下,成员已经被应用了支持序列化的标签。如果这个类标注这个标签,可以定制这种类型的序列化过程。
public interface ISerializable
{
void GetObjectData(
SerializationInfo info,
StreamingContext context
);
}
在.NET 中,所有的值类型都支持序列化。对于类来说,应用Serializable标签的类将支持序列化操作。例如,常见的System.String,List<T> ,Dictionary<TKey,TValue>,ArrayList 等类型都支持序列化操作。