您的位置:首页 > 编程语言 > C#

《CLR via C#:框架设计》读书笔记 - 运行时序列化

2016-04-22 00:52 471 查看
序列化(serialization)是将一个对象或者对象图转换成字节流的过程。反序列化(deserialization)是将一个字节流转换会对象的过程。在对象和字节流之间转换时非常有用的机制。下面是一些例子:

应用程序的状态(对象图)可以保存到磁盘文件或数据库,并在应用程序下次运行时恢复。如asp.net就是利用它来保持和恢复会话状态的。

一个对象可以轻松复制到系统的剪贴板,在粘贴会同一个或另一个应用程序。windows窗体和wpf就是利用这个功能。

一组对象可以可以轻松的通过网络发给另一台机器上运行的进程。Microsoft .net framework的Remoting架构会对按值封送的对象进行序列化和反序列化。这个技术还可以跨越AppDomain边界发送对象。

除了上述应用,一旦将对象序列化为内存中的一个字节流,可以使用一些更有用的方式来方便的处理数据,比如加密和压缩数据等。

24.1 序列化/反序列化快速入门

返回

复制代码

1 using System.IO;

2 using System.Reflection;

3 using System.Runtime.Serialization;

4 using System.Runtime.Serialization.Formatters.Binary;

5

6 internal static class QuickStart {

7 public static void Go() {

8 // Create a graph of objects to serialize them to the stream

9 var objectGraph = new List { “Jeff”, “Kristin”, “Aidan”, “Grant” };

10 Stream stream = SerializeToMemory(objectGraph);

11

12 // Reset everything for this demo

13 stream.Position = 0;

14 objectGraph = null;

15

16 // Deserialize the objects and prove it worked

17 objectGraph = (List)DeserializeFromMemory(stream);

18 foreach (var s in objectGraph) Console.WriteLine(s);

19 }

20

21 private static MemoryStream SerializeToMemory(Object objectGraph) {

22 // Construct a stream that is to hold the serialized objects

23 MemoryStream stream = new MemoryStream();

24

25 // Construct a serialization formatter that does all the hard work

26 BinaryFormatter formatter = new BinaryFormatter();

27

28 // Tell the formatter to serialize the objects into the stream

29 formatter.Serialize(stream, objectGraph);

30

31 // Return the stream of serialized objects back to the caller

32 return stream;

33 }

34

35 private static Object DeserializeFromMemory(Stream stream) {

36 // Construct a serialization formatter that does all the hard work

37 BinaryFormatter formatter = new BinaryFormatter();

38

39 // Tell the formatter to deserialize the objects from the stream

40 return formatter.Deserialize(stream);

41 }

42 }

复制代码

FCL提供了两个格式化器:Binaryformatter和SoapFormatter。要序列化一个对象图,只需调用格式化器的Serialize方法 。方法原型如下:

1 public void Serialize(Stream serializationStream, object graph);

格式化器调用Serialize方法是,为了确保对象图中所有对象都被序列化到流中,格式器会参考每个类型的元数据。序列化时,利用反射来查看每个对象类型中有哪些实例字段,这些实例字段中,又有哪些引用了其他对象,然后对他们进行序列化。

序列化是应注意:

1)使用相同的格式化器进行序列化和反序列化。

2)序列化一个对象时,类型的全名和类型定义的程序集名称会被写入流。在反序列化是,会用这些信息,会用System.Reflection.Assembly.Load方法加载程序集,再在程序集中找到匹配的类型,找到后创建类型的实例,并用流中的值对其字段进行初始化。

24.2 使类型可序列化

返回

FCL得内置类型或者说基元类型已经标识的特性[Serializable],使得他们可序列化。

使类型可序列化语法很简单,只需在类上标上特性[Serializable],它是在System命名空间中定义的。

SerializableAttribute这个特性只能应用于引用类型、值类型。除此之外,这个特性是不会被派生类继承的;反之,则不亦然因此System.Object标识了这个特性。

24.3 控制序列化和反序列化

返回

类标识上特性[Serializable]后,所有实例字段(public,private,protected)都会被序列化,有时我们不希望某些字段被实例化,如下情况:

字段之在当前进程内有效,如句柄。

字段含有很容易计算的信息

标识字段不需序列化也很简单,只需在字段前标上特性[NonSerializable]即可。注意:该特性不会被派生类继承。

但当一个字段没有序列化,会在反序列化化是出现问题,如某些方法用到这个字段,需要当前值,FCL提供了以下方法:

复制代码

1 [OnSerializing]

2 private void OnSerializing(StreamingContext context)

3 {//在序列化前,修改任何需要修改的状态 }

4 [OnSerialized]

5 private void OnSerialized(StreamingContext context)

6 {//在序列化后,恢复任何需要修改的状态 }

7

8 [OnDeserializing]

9 private void OnDeserializing(StreamingContext context)

10 {//在反序列化前,修改任何需要修改的状态 }

11 [OnDeserialized]

12 private void OnDeserialized(StreamingContext context)

13 {// 在反序列化后,恢复任何需要修改的状态}

复制代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  读书笔记 C#