《Effective C#》读书笔记——条目27:让类型支持序列化<使用C#表达设计>

  持久化(persistence)是类型的一个重要特性。只要我们的类型不是UI控件、窗体或者表单,都应该尽可能的为类型添加序列化支持。.NET的序列化是把类中所有成员变量保存到输出流中,同时.NET的序列化还支持任意的对象图(object graph):即使你的对象上有一个循环引用,serialize 和deserialize 方法都只会为你的实际对象读取和储存一次。

 

1. .NET的序列化支持

  在.NET中支持序列化是一件非常简单的任务,在绝大多数的情况下,只需要添加一个Serializable特性就可以了。但是这里有一个前提:

使用Serializable特性对类进行序列化支持,要求该类的所有成员都是可序列化的。

 

例如,下面的例子,由于int和string类型都是支持.NET序列化,所有我们只需要简单的添加Serializable特性即可。

1     [Serializable]
2     public class MyType
3     {
4         private string lable;
5         private int value;
6     }

 

反之,如果在一个类中如果有成员不支持序列化,而又使用Serializable,例如下面的代码中,由于OhterClass类没有序列化支持,在序列化MyType时,会得到一个运行时错误。

1 [Serializable]
2 public class MyType
3 {
4     private string lable;
5     private int value;
6     private OtherClass other;
7 }

 

2.正确的初始化使用NonSerialized特性的成员

  添加Serializable特性是支持对象序列化的最简单方式,但最简单的方式却不一定总是这却的方式。假如:我们并不想序列化对象的所有成员:比如某些成员可能只存在于与长期操作的缓存中、或者占用着一些运行时资源,而这些资源只存在于与内存中时我们该如何解决这一问题呢?同样,我们可以通过添加NonSerialized特性到任何你不想让它序列化的数据成员上:

1     [Serializable]
2     public class MyClass
3     {
4         public int Id{get;set;}
5         [NonSerialized]
6         public int CachedValue{get;set;}
7         public string Name{get;set;}
8     }

 

  当我们使用NonSerialized特性时,我们同时也需要完成一些额外的工作:因为在反序列化的过程中.NET序列化API不会初始化使用NonSerialized特性的成员,同时由于类型的构造函数不会被调用,所有成员的初始化器也就不会被执行。当使用Serializable特性时,那些使用NonSerialized特性的成员只会得到系统设定的默认值:0或null(值类型或引用类型);如果系统默认的初始化行为并不是我们想要的效果,那么着时候我们可以通过实现IDeserializationCallback接口来对这些成员进行初始化。在整个对象图被反序列化之后,.NET会自动调用该接口唯一的OnDeserialization()方法。

 

posted @ 2013-02-28 21:22  gyzhao  阅读(346)  评论(0编辑  收藏