博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《CLR via C#》读书笔记 之 运行时序列化
阅读量:6858 次
发布时间:2019-06-26

本文共 3478 字,大约阅读时间需要 11 分钟。

第二十四章 运行时序列化

2013-04-10

 

序列化(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
{ "Jeff", "Kristin", "Aidan", "Grant" };10 Stream stream = SerializeToMemory(objectGraph);11 12 // Reset everything for this demo13 stream.Position = 0;14 objectGraph = null;15 16 // Deserialize the objects and prove it worked17 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 objects23 MemoryStream stream = new MemoryStream();24 25 // Construct a serialization formatter that does all the hard work26 BinaryFormatter formatter = new BinaryFormatter();27 28 // Tell the formatter to serialize the objects into the stream29 formatter.Serialize(stream, objectGraph);30 31 // Return the stream of serialized objects back to the caller32 return stream;33 }34 35 private static Object DeserializeFromMemory(Stream stream) {36 // Construct a serialization formatter that does all the hard work37 BinaryFormatter formatter = new BinaryFormatter();38 39 // Tell the formatter to deserialize the objects from the stream40 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 {
// 在反序列化后,恢复任何需要修改的状态}

 

转载地址:http://wtjyl.baihongyu.com/

你可能感兴趣的文章
笨办法学 Python · 续 练习 23:三叉搜索树
查看>>
可穿戴设备不能急于戴上“智能”的高帽子
查看>>
扒一扒政府的专用黑客组织ZooPark
查看>>
Ubuntu下Deb软件包相关安装与卸载
查看>>
互联网转型需要微服务架构
查看>>
Airbus Safran Launchers:选择西门子彻底改革产品生命周期流程
查看>>
文本数据的分分合合
查看>>
无损音乐知识收集2(转)
查看>>
vim 工具(一)
查看>>
MySQL常用命令
查看>>
zabbix snmp监控
查看>>
MySQL单实例重置密码的两种方法
查看>>
一段典型的PHP程序都包含那些内容呢?
查看>>
Windows Phone 7 数据绑定的简单介绍
查看>>
合并下载的Solaris镜像为DVD文件的方法
查看>>
shell编程入门步步高(一、shell简介)
查看>>
一个简单的HQL优化
查看>>
从股价说起 百神大战凸现百度与腾讯阿里差距
查看>>
MariaDB六之主从复制
查看>>
outlook cannot send this item
查看>>