序列化就是将内存中的对象保存成可存或可传的形式。一般情况下,对象是根据类被实例化到托管堆上的,一旦进程退出,整个对象被释放掉,如果再次实例化类,所得的对象,与先前的对象状态是不一样的,为此,序列化就成为一个有效的解决方式。
下面先看一个例子:
新建一个WinForm项目,在Form1窗体上放两个Button,分别为Button1和Button2。
在Form1对应的cs代码中,引入下列命名空间:
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Permissions;
然后添加下面两个类:
public class Person
{
public bool sex;
}
[Serializable]
public class Chinese : Person,ISerializable
{
public string complexion;
public Chinese()
{ }
public Chinese(SerializationInfo info, StreamingContext context)
{
sex = info.GetBoolean("sex");
complexion = info.GetString("complexion");
}
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("sex", sex);
info.AddValue("complexion", complexion);
}
}
再处理两个Button的单击事件订阅的方法:
//序列化XiaoHong对象
private void button1_Click(object sender, EventArgs e)
{
Chinese XiaoHong = new Chinese();
XiaoHong.sex = true ;
XiaoHong.complexion = "Yellow";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("F:/xh.bin", FileMode.Create, FileAccess.Write, FileShare.None); ;
formatter.Serialize(stream, XiaoHong);
stream.Close();
}
//反序列化XiaoHong对象
private void button2_Click(object sender, EventArgs e)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("F:/xh.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
Chinese XiaoHong = (Chinese)formatter.Deserialize(stream);
stream.Close();
MessageBox.Show(string.Format("性别:{0},肤色:{1}", XiaoHong.sex, XiaoHong.complexion));
}
其实序列的用法相对简单,在这里,要说两个地方,一个是GetObjectData引入的属性[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)],这是一个设置数据访问的权限属性。另一个是GetObjectData的两个参数SerializationInfo info和 StreamingContext context,其中info是保存序列化对象中数据的类,context是对序列化流的描述。可能这时候不明白这些属性,下来,说一下序列化的本质吧。
这要从C#面向对象的类说起,我们知道,在类中,成员有字段,属性,方法,索引器,操作符,内部类等,但这些东西,最终都可以归为两大类,一种就是存数据的,一种就是执行功能的。在类成员中,存数据的,就是字段了(属性其实不是用来存放数据的,属性是由get和set两个方法封装成的),其他的成员,都是用来完成一定功能。完成功能的在类成员中,方法是比较常见的。
为什么要说类成员呢?因为在对象序列化时,保存的只有数据,而功能是不保存的。我们如果把序列化后的文件xh.bin用文本打开,内容如下:
���� OWindowsFormsApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null WindowsFormsApplication3.Chinese sex
complexion Yellow
从上面的文件可看出,有两个字段sex和complexion,这两个是字段,是用来存储的数据项,所以在序列化过程中是只保存对象的数据,至于方法,是不保留的,因为在对象的生存周期内,方法是不变的,所以在返序列化过程中,方法可以从类中得到,而数据则是从文件中得到。还要注意的一点是,我们在做序列化类的时候,提到过一个SerializationInfo info的一个参数,正是这个info,把类中的字段数据当成一个整体,保存了下来,即GetObjectData方法内的代码。在反序列化过程中,正要进行上面相反的过程,反序列是对象重现的过程,所以在类的构造函数中,把字段数据从info中取出来,赋给字段,完成对象的重现。
总结一句话,序列化就是把对象中的数据按一定规则组织成文件存储或组织成网络流进行传输(Remoting中用到)。