【狼窝乀野狼】Serializer妙手回春

  在我们很多程序中,需要将数据保存到本地,以便于下次打开还能看到原始数据。例如我们Xmind思维导图,例如我们的Power Designer等等,都是有保存一个隶属于自己的工程文件,那么今天我要说的就是,工程文件中的序列化和反序列化。

【简介】

  序列化就是就爱那个对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私有字段以类的名称(包括类的程序集)转为字节流,然后再把字节流写入数据流,在随后对对象进行反序列化的时候,将创建与原来对象相同的副本。

【为什么要序列化?序列化的好处是什么?】

1、将对象的状态保存在存储媒体中,以便于可以在以后重新创建出来完全相同副本。

2、按值将对象从一个应用程序域发送到另一个应用程序域。这样可以方便内存对象变成磁盘数据,便于网络传输,用于分布式,WCF等应用(JSON其实就是将对象序列化为字符串)。实现对象的备份和还原。

【持久储存】

我们经常需要将对象的字段值保存到磁盘中,并在以后检索这些数据。尽管我们不采用序列化也可以做到这事儿,但是通常这种方法比较繁琐而且容易出现差错。在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象如果我们在进行编写一个包含大量对象的大型的业务应用程序的时候,开发人员不得不为每个对象编写代码,以便于将字段和属性保存到磁盘中以及从磁盘中还原这些对象和属性。而序列化提供了轻松快捷实现这个目标的方法。

【序列化种类】

一种是二进制序列化。将对象转为二进制文件。

二种是XML序列化。将对象转为XML文件的方式。

二者之间不同于,前者将所有的成员变量(包含 private,protected,public)字段或者属性进行序列化;后者只将公有字段和属性进行序列化。

【序列化方式】

想要将一个类进行序列化,首先需要将其标记可序列化([Serializable])。通常我们采用两种方式进行序列化,一种是自动序列化,只需要在类名头上面添加[Serializable]特性标签即可。另一种是手动序列化,需要添加[Serializable]特性标签并且实现ISerializable接口。

自动序列化的好处在于,我们可以人为地将一些字段或者属性进行序列化。当然在自动序列化过程中,只要我们将不需要序列化的字段或者属性标记上[NonSerialized],那么这个字段或者属性,就不会被序列化。

自动序列化,系统是采用"<FileName>k__BackingField"

例如上面一个数据建模,在自动序列化中

1     [Serializable]
2     public class Person
3     {
4         public int Age { get; set; }
5
6         public string Name { get; set; }
7     }

在自动序列化文件中,存在形式如下:

手动序列化

 1     [Serializable]
 2     public class Animal:ISerializable
 3     {
 4         public int Age { get; set; }
 5
 6         public string Name { get; set; }
 7
 8         public Animal()
 9         {
10
11         }
12
13         private Animal(SerializationInfo info, StreamingContext context)
14         {
15             Age = info.GetInt32("Age");
16             Name = info.GetString("Name");
17         }
18
19         public void GetObjectData(SerializationInfo info, StreamingContext context)
20         {
21             info.AddValue("Age", Age);
22             info.AddValue("Name", Name);
23         }
24     }

通过两种方式对比,我们看出,手动序列化,可以指定我们一个属性或者字段在磁盘中映射名称。

【工程兼容问题】

既然我们在做开发,那么就可能因为业务的需要,对以前的数据建模进行修改。例如在原来的建模中添加一个属性等。如果添加一个属性,那么在反序列化的时候就会出现问题,导致打开工程失败。原因在于,例如以前序列化的一个对象,里面包含了三个字段,但是在反序列化的时候,你需要反序列化四个字段,那么就会导致失败。

做工程兼容,首先需要查看以前的建模是采用自动序列化还是手动序列化。如果是自动序列化,你需要将自动序列化变成手动序列化,其次我们需要判断里面某个属性存在不。

 1     [Serializable]
 2     public class Animal:ISerializable
 3     {
 4         public int Age { get; set; }
 5
 6         public string Name { get; set; }
 7
 8         public Animal()
 9         {
10
11         }
12
13         private Animal(SerializationInfo info, StreamingContext context)
14         {
15             //Age = info.GetInt32("Age");
16             //Name = info.GetString("Name");
17             var serializedData = GetSerializedData(info);
18             var currentData = GetSerializableData();
19             foreach (var memberInfo in serializedData)
20             {
21                 var val = memberInfo.Value;
22                 if (val == null)
23                 {
24                     continue;
25                 }
26                 if (currentData.ContainsKey(memberInfo.Key))
27                 {
28                     currentData[memberInfo.Key](val);
29                 }
30             }
31         }
32
33         public void GetObjectData(SerializationInfo info, StreamingContext context)
34         {
35             info.AddValue("Age", Age);
36             info.AddValue("Name", Name);
37         }
38
39         /// <summary>
40         /// 当前类中字段或者属性射影
41         /// </summary>
42         /// <returns></returns>
43         private Dictionary<string, Action<object>> GetSerializableData()
44         {
45             return new Dictionary<string, Action<object>>
46             {
47                 {"Age",value=>Age = (int)value},
48                 {"Name",value=>value.ToString()}
49             };
50         }
51
52         /// <summary>
53         /// 序列化中,字段或者属性的射影
54         /// </summary>
55         /// <param name="info"></param>
56         /// <returns></returns>
57         private Dictionary<string, object> GetSerializedData(SerializationInfo info)
58         {
59             var serializs = info.GetEnumerator();
60             Dictionary<string, object> dic = new Dictionary<string, object>();
61             while (serializs.MoveNext())
62             {
63                 dic.Add(serializs.Current.Name, serializs.Current.Value);
64             }
65             return dic;
66         }
67     }

如果新的需求,需要在建模中添加字段或者属性,我们只需要,在GetObjectData中添加需要序列化的字段,在GetSerializableData,添加反序列化的处理。这样,不管添加多少个字段,我们都可以在新的工程中打开以前的数据。

【总结】

  技术不在于牛不牛,只在于问题你遇见过没有,处理成功没有。当一天你遇到问题足够多,解决问题足够多,你也成为了站在塔尖上耀眼的那个人。今天的内容有点粗糙,可能以前可有人板书过的,可能我在这里有点画蛇添足,而且笔锋也在有点飘逸零乱,下次再将我们如果在程序中修改了程序集名称,如何处理兼容性问题。

时间: 2024-07-30 10:15:49

【狼窝乀野狼】Serializer妙手回春的相关文章

【狼窝乀野狼】Parallel浅尝辄止

前段时间看到园子里面有同学在用Parallel进行批量插入数据库.后面也有很多同学针对这一事件给出了自己的看法和见解.我在这里不评论内容的好坏,至少能将自己东西总结分享这个是要靠勇气和毅力. 闲话少说,我在最近看崔鹏飞的github的时候,发现他对这块也做了一定的总结,那么我就他这块进行板书与展示.案例是怎么回事呢?话说我有一个公司,里面需要统计一下总收入,另外有一个公司被我收购了,我一起计算总收入.当一天我收购了N个公司,计算总收入的时候,我们采用并行计算. 1 internal class

SpringMVC+Hibernate返回JSON数据报No serializer found错误

在使用SpringMVC+Hibernate环境中返回JSON数据有时会出现如下错误:Handler execution resulted in exception: Could not write content: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializ

jQuery DataTables &amp;&amp; Django serializer

jQuery DataTables https://www.datatables.net 本文参考的官方示例 http://datatables.net/release-datatables/examples/ajax/objects.html 关于Python序列化 http://www.cnblogs.com/linyawen/archive/2012/03/22/2411381.html Django中的Models序列化 http://www.weiguda.com/blog/19/ P

Yii2.0 初识 RESTful Serializer

当RESTful API响应中包含一个资源时,该资源需要序列化成一个字符串. Yii将这个过程分成两步,首先,资源会被yii\rest\Serializer转换成数组, 然后,该数组会通过yii\web\ResponseFormatterInterface根据请求格式(如JSON, XML)被序列化成字符串.当开发一个资源类时应重点关注第一步. 所以打开Yii框架下的vendor/yiisoft/yii2/rest/Serializer.php     public $fieldsParam =

野狼伴我劳作,满天星斗的夜空

记得,在1968年11月7日,作为<五七干校>的第一批先遣队员,我们来到北大荒小新安岭的南麓,面对乌鱼尔(日语)河畔.到处是一望无际的黑土地,荒无人烟. 我离开北京时候,身边带上了一个温度计(室内专用),结果无法使用,因为,温度计的指示刻度太高,无法反应室外的寒冷天气.那时光,我们只能住在绵帐蓬里面,牙膏冻成了冰棍,挤不出里面的牙膏.没有电灯光的夜晚,满天星斗,心旷神怡. 次年开春,因为那里的无霜期只有一百天(三个月),必须抢时间,按照当地农时耕地.播种,田间管理,收获粮食,......周围的

Spring Data Redis简介以及项目Demo,RedisTemplate和 Serializer详解

一.概念简介: Redis: Redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写,详细的信息在Redis官网上面有,因为我自己通过google等各种渠道去学习Redis,走了不少弯路,所以总结一条我认为不错的学习路径给大家: 1.<The Little Redis Book> 是一本开源PDF,只有29页的英文文档,看完后对Redis的基本概念应该差不多熟悉了,剩下的可以去Redis官网熟悉相关的命令. 2.<Redis设计与实现> 如果想继续深入,推

jvm serializer 功能&amp;性能基准测试

开源项目jvm serializer介绍: 该项目分析了目前主流分布式通讯相关开源产品中使用的No Schema序列化产品Kryo,Fastjson,Hessian的序列化机制,通过构造相对比较复杂的数据model,针对序列化size,序列化时间进行了细致测试.通过测试报告可以清晰的看出Kryo无疑是大赢家,无论是序列化大小,还是速度上都更胜一筹,这也就不难理解为什么Spark,Storm等流计算框架会选它作为序列化工具.另外,可以看出这三款软件在BitSet,EnumSet等特殊类型的序列化上

使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的解决

应用场景 我们希望通过缓存来减少对关系型数据库的查询次数,减轻数据库压力.在执行DAO类的select***(), query***()方法时,先从Redis中查询有没有缓存数据,如果有则直接从Redis拿到结果,如果没有再向数据库发起查询请求取数据. 序列化问题 要把domain object做为key-valuec对保存在redis中,就必须要解决对象的序列化问题.Spring Data Redis给我们提供了一些现成的方案: JdkSerializationRedisSerializer.

日志log使用序列反序列加密(Serializer) DESCrypto 加密

若一次加密一个文件内容,文件内容不会更新变化,网上大多数序列化反序列加密程序是没问题的. 1:由于log文件的随时会更新内容,那网上常用的程序是行不通的.需要做修改 若想通过打开txt , using (var file =new  FileStream(path,FileMode.Append))  简单的扩展append 命令,结果是新加的内容会显示不出来. 或者两段不同时期写入的log的内容中间是乱文的,因为文件模式为append ,扩展新行,这个命令是两段文字之间加上了换行符吧,具体加的