在我们很多程序中,需要将数据保存到本地,以便于下次打开还能看到原始数据。例如我们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,添加反序列化的处理。这样,不管添加多少个字段,我们都可以在新的工程中打开以前的数据。

【总结】

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

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

  1. 【狼窝乀野狼】Excel那些事儿

    在工作中我们常常遇到Excel表格,不管是数据的导入导出,还是财务统计什么都,都离不开Excel,Excel是我见过的最牛逼的一个软件(可能我的见识少)没有之一:如果你只停留在Excel处理数据,统计 ...

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

    前段时间看到园子里面有同学在用Parallel进行批量插入数据库.后面也有很多同学针对这一事件给出了自己的看法和见解.我在这里不评论内容的好坏,至少能将自己东西总结分享这个是要靠勇气和毅力. 闲话少说 ...

  3. 【狼窝乀野狼】Windows Server 2008 R 配置 Microsoft Server 2008 远程登录连接

    如果你已经了解了,或者你已经经历了,那么此篇文章对你是毫无用处.因为文笔深处未必有自己亲身体验来的真实有效. 闲话少说,直接上菜. 最近脑子“抽筋”,想安装一个服务器来玩玩,那么怎么选择呢?我的PC是 ...

  4. Django Restful Framework (一): Serializer

    Serializer 允许复杂数据(比如 querysets 和 model 实例)转换成python数据类型,然后可以更容易的转换成 json 或 xml 等.同时,Serializer也提供了反序 ...

  5. Serializer序列化/反序列化DateTime少了8小时问题解决

    1.举例子 JavascriptSerializer serializer = new JavascriptSerializer(); DateTime now = DateTime.Parse(&q ...

  6. jQuery DataTables && Django serializer

    jQuery DataTables https://www.datatables.net 本文参考的官方示例 http://datatables.net/release-datatables/exam ...

  7. 【hibernate 报错】No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer 【get和load的区别】

    报错: HTTP Status 500 - Could not write content: No serializer found for class org.hibernate.proxy.poj ...

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

    若一次加密一个文件内容,文件内容不会更新变化,网上大多数序列化反序列加密程序是没问题的. 1:由于log文件的随时会更新内容,那网上常用的程序是行不通的.需要做修改 若想通过打开txt , using ...

  9. Replace JSON.NET with Jil JSON serializer in ASP.NET Web API

    I have recently come across a comparison of fast JSON serializers in .NET, which shows that Jil JSON ...

随机推荐

  1. CSS选择器笔记

    一.元素选择符 序号 选择器 含义 1. * 通用元素选择器,匹配任何元素 2. E 标签选择器,匹配所有使用E标签的元素 3. .info class选择器,匹配所有class属性中包含info的元 ...

  2. 递归小Demo

    public class demo5 { public static void main(String[] args) {        //初始值为100         int n = 100;  ...

  3. .NET DLL 保护措施应用实例(百度云分享工具)

    最近做了个小工具,将保护措施思路全部应用到了此工具中. 点我下载 “百度分享工具”介绍 大家都知道,在百度云盘中分享文件,只能手工一条条地点击“分享”,如果想分享很多文件,操作会非常辛苦.“百度云分享 ...

  4. SVN Server导项目到本地库时提示"方法OPTIONS失败与无法连接到服务器"

    方法 OPTIONS 失败于 “https://xxxx/svn/xxxx”: 无法连接到服务器 (https://xxxx) 要留意  https 使用了443 端口,检查防火墙是否开放了该端口. ...

  5. 苹果在Xcode6中弃用segue的push和model

    苹果在Xcode6中弃用了segue的push和model.被show和present取代. 下面是新版本中每种类型的使用总结和例子.建议自己使用前先在测试项目中自己试一试 Show 根据当前屏幕中的 ...

  6. linux 系统运行级别及修改[转]

    Linux运行级别从0-6,共7个. 0:关机.不能将系统缺省运行级别设置为0,否则无法启动. 1:单用户模式,只允许root用户对系统进行维护. 2:多用户模式,但不能使用NFS(相当于Window ...

  7. hibernate 一对多映射关系

    1.   单项多对一映射       custom(顾客)与order(订单) :一个顾客可以有多个订单,一个订单只能有一个顾客       配置方法:在多的一端配置<many -to one& ...

  8. 大数求模 sicily 1020

        Search

  9. 3月3日(6) Climbing Stairs

    原题 Climbing Stairs 求斐波那契数列的第N项,开始想用通项公式求解,其实一个O(n)就搞定了. class Solution { public: int climbStairs(int ...

  10. 水仙花数 java 实现

    题目描述: 春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的:“水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3.现在要求 ...