吴佳鑫的个人专栏

当日事当日毕,没有任何借口

导航

对象序列化(三):控制序列化过程

接着上一节的内容,有时候我们在对象中,并不是所有的字段需要序列化。

 

示例:

以下是这个窗体需要用到的实体类

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Collections;

namespace MutliObjectSerialization2
{
[Serializable]
class CollegeStudent:IDeserializationCallback
{
public String Name="";//姓名
public bool IsMale=true ; //性别
public int ScoreForEntranceExamination=0; //入学考试成绩
public DateTime BirthDay=DateTime.Now; //生日
[NonSerialized]
public int Age=0; //年龄
void IDeserializationCallback.OnDeserialization(Object sender)
{
Age=DateTime.Now.Year-BirthDay.Year ;
}
}

[Serializable]
class StudentList//学生清单
{
public List<CollegeStudent> Students = new List<CollegeStudent>();//学生对象集合
}
}

我们仔细想想,会发现“年龄”字段很特殊,它直接依赖于“生日”字段的值,而且会随着时间的推移而发生变化。如果在序列化时,将此字段也序列化到文件中,那么无论什么时候重建对象,“年龄”字段的值都是不变的。这显然不符合实际情况。

其实,只要知道了生日,拿当时日期一减,就可知道这个人的年龄,因此可以选择不序列化“年龄”字段,而在反序列化对象时“现场”计算年龄再填入。这就需要对.net framework默认的对象序列化过程进行一定的调整。

 

在.net framework中,给类的一个字段加上 [NonSerialized] 标记,即可让此字段不参与序列化。

 

.net framework还提供了一个 IDeserializationCallback 接口,它定义了一个 OnDeserialization 方法,可在反序列化完成时自动调用这一方法。换名话说:如果让 CollegeStudent类实现IDeserializationCallback接口(即提供一个OnDeserialization方法),则从流中重建CollegeStudent对象完成时,CLR会自动调用已定义好的OnDeserialization方法,可以在这个方法中写代码对年龄进行计算并填充“年龄”字段。

 

本日记介绍了用[NonSerialized]标记和 IDeserializationCallback 接口来控制序列化过程。除此之外,framework还提供了以下4个代码标记用于提供更多的控制手段。

[OnSerializedAttribute] : 在序列化完成后调用。

[OnSerializingAttribute] : 在序列化进行时调用。

[OnDeSerializedAttribute] :在反序列化完成后调用。

[OnDeSerializingAttribute] : 在反序列化进行时调用。

将这些标记附加到方法上(一个方法只能附加一个标记),则在合适的时机这些方法会被自动调用。

posted on 2012-02-14 23:18  _eagle  阅读(457)  评论(0编辑  收藏  举报