《CLR via C#》读书笔记 之 运行时序列化 明

第二十四章 运行时序列化

2013-04-10

24.1 序列化/反序列化快速入门
24.2 使类型可序列化
24.3 控制序列化和反序列化

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

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

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

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

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

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


返回

View Code
 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<String> { "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<String>)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方法 。方法原型如下:

View Code
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提供了以下方法:

View Code
 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       {// 在反序列化后,恢复任何需要修改的状态}
原文地址:https://www.cnblogs.com/Ming8006/p/3012778.html