接着上一节的内容,有时候我们在对象中,并不是所有的字段需要序列化。
示例:
以下是这个窗体需要用到的实体类
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 ListStudents = new List ();//学生对象集合 } }
我们仔细想想,会发现“年龄”字段很特殊,它直接依赖于“生日”字段的值,而且会随着时间的推移而发生变化。如果在序列化时,将此字段也序列化到文件中,那么无论什么时候重建对象,“年龄”字段的值都是不变的。这显然不符合实际情况。
其实,只要知道了生日,拿当时日期一减,就可知道这个人的年龄,因此可以选择不序列化“年龄”字段,而在反序列化对象时“现场”计算年龄再填入。这就需要对.net framework默认的对象序列化过程进行一定的调整。
在.net framework中,给类的一个字段加上 [NonSerialized] 标记,即可让此字段不参与序列化。
.net framework还提供了一个 IDeserializationCallback 接口,它定义了一个 OnDeserialization 方法,可在反序列化完成时自动调用这一方法。换名话说:如果让 CollegeStudent类实现IDeserializationCallback接口(即提供一个OnDeserialization方法),则从流中重建CollegeStudent对象完成时,CLR会自动调用已定义好的OnDeserialization方法,可以在这个方法中写代码对年龄进行计算并填充“年龄”字段。
本日记介绍了用[NonSerialized]标记和 IDeserializationCallback 接口来控制序列化过程。除此之外,framework还提供了以下4个代码标记用于提供更多的控制手段。
[OnSerializedAttribute] : 在序列化完成后调用。
[OnSerializingAttribute] : 在序列化进行时调用。
[OnDeSerializedAttribute] :在反序列化完成后调用。
[OnDeSerializingAttribute] : 在反序列化进行时调用。
将这些标记附加到方法上(一个方法只能附加一个标记),则在合适的时机这些方法会被自动调用。