《CLR via C#》之运行时序列化

  今天,抽空完成下序列化的学习。主要是通过阅读Jeffrey Cichter的《CLR Via C#》。2012-04-10

CLR via C# 之运行时序列化

Serialize Quick Start

我们通过一段代码来开始我们的学习之旅。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.IO;
 4 using System.Linq;
 5 using System.Runtime.Serialization.Formatters.Binary;
 6 using System.Text;
 7 
 8 namespace SerializeQuickStart
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             var objectGraph = new List<String> { "Name1", "Name2", "Name3" };
15             Stream stream = SerializeToMemory(objectGraph);
16             stream.Position = 0;
17             objectGraph = null;
18 
19             objectGraph = (List<String>)DeserializeFromMemory(stream);
20             foreach (var name in objectGraph)
21             {
22                 Console.WriteLine(name);
23             }
24         }
25 
26         private static Stream SerializeToMemory(object objectGraph)
27         {
28             MemoryStream memoryStream = new MemoryStream();
29             BinaryFormatter formatter = new BinaryFormatter();
30             formatter.Serialize(memoryStream, objectGraph);
31             return memoryStream;
32         }
33 
34         private static object DeserializeFromMemory(Stream stream)
35         {
36             BinaryFormatter formatter = new BinaryFormatter();
37             return formatter.Deserialize(stream);
38         }
39     }
40 }

  看完上面一段代码,我们会觉得序列化其实也很简单。SerializeToMemory方法构造了System.IO.MemoryStream对象。我们把序列化好的字节块放到内存流对象中。然后方法通过BinaryFormatter对象的实例,序列化传入的对象。FCL(Framework Class Library)提供了两个格式化器:BinaryFomatter和SoapFomatter。想要序列化一个对象,只需要使用格式化器中的Serialize和Deserialize方法就可以达到目的了。

  从上面一段代码中,我们需要注意几点。其一,序列化和反序列化的格式化器要一致。其二,当序列化时,确保流的位置被置为0。其三,我们可以将多个对象序列化到同一个流中。(序列化对象的顺序与反序列化的顺序必须一致,比方说你序列化的顺序为A,B,C,你反序列化的顺序也应该为A,B,C。)其四,最重要的一项,序列化一个对象的时候,类型的全名和类型的定义程序集的名称会被写入流。有的扩展程序使用Assembly.LoadFrom加载一个程序集,然后根据加载的程序集中定义的类型来构造对象。这些对象可以毫无问题地序列化到流中。然而,反序列化流时,格式化器会通过调用Assembly的Load方法来尝试加载程序集。在书中,Jeffrey Richter建议实现一个方法,方法签名匹配System.ResolveEventHandler(Deserialze方法返回结果后,马上向事件注销这个方法。)这个方法用来防止反序列化中可能找不到程序集。

Make Class Serializable

  当我们定义一个类时,默认是不可序列化的。如何让一个自定义的类能够被序列化呢?很简单,为这个类打上SerializableAttribute,这个定制attribute只能应用于类型(class)、值类型(struct)、枚举值(enum)和委托类型(delegate)。注意,枚举和委托总是可序列化的。

Control Serialize

  我们需要控制序列化,如果字段含有反序列化后变得无效的信息,或者字段容易被计算得到。这些字段,建议打上NonSerializedAttribute定制attribute来指定类型中哪些字段不应序列化。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.IO;
 4 using System.Linq;
 5 using System.Runtime.Serialization;
 6 using System.Runtime.Serialization.Formatters.Binary;
 7 using System.Text;
 8 
 9 namespace ControlSerializtion
10 {
11     internal class Program
12     {
13         static void Main(string[] args)
14         {
15             Circle circle = new Circle(10);
16             MemoryStream memoryStream = new MemoryStream();
17             BinaryFormatter formatter = new BinaryFormatter();
18             formatter.Serialize(memoryStream, circle);
19             memoryStream.Position = 0;
20             circle = null;
21             circle = (Circle)formatter.Deserialize(memoryStream);
22             Console.WriteLine(circle.Area);
23         }
24     }
25 
26     [Serializable]
27     internal class Circle
28     {
29         private Double m_radius;
30 
31         [NonSerialized]
32         private Double m_area;
33 
34         public Circle(Double radius)
35         {
36             m_radius = radius;
37             m_area = Math.PI * m_radius * m_radius;
38         }
39 
40         [OnDeserialized]
41         private void OnDeserialized(StreamingContext context)
42         {
43             m_area = Math.PI * m_radius * m_radius;
44         }
45 
46         public Double Area { get { return m_area; } }
47     }
48 }


下节更精彩,讲解格式化器是如何序列化类型的实例的。^.^ 2012-04-10

转载于:https://www.cnblogs.com/OliverZh/archive/2012/04/10/CLRViaCSharp1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值