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

【简介】

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

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

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

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

【持久储存】

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

【序列化种类】

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

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

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

【序列化方式】

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

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

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

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

     [Serializable]
public class Person
{
public int Age { get; set; } public string Name { get; set; }
}

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

手动序列化

     [Serializable]
public class Animal:ISerializable
{
public int Age { get; set; } public string Name { get; set; } public Animal()
{ } private Animal(SerializationInfo info, StreamingContext context)
{
Age = info.GetInt32("Age");
Name = info.GetString("Name");
} public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Age", Age);
info.AddValue("Name", Name);
}
}

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

【工程兼容问题】

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

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

     [Serializable]
public class Animal:ISerializable
{
public int Age { get; set; } public string Name { get; set; } public Animal()
{ } private Animal(SerializationInfo info, StreamingContext context)
{
//Age = info.GetInt32("Age");
//Name = info.GetString("Name");
var serializedData = GetSerializedData(info);
var currentData = GetSerializableData();
foreach (var memberInfo in serializedData)
{
var val = memberInfo.Value;
if (val == null)
{
continue;
}
if (currentData.ContainsKey(memberInfo.Key))
{
currentData[memberInfo.Key](val);
}
}
} public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Age", Age);
info.AddValue("Name", Name);
} /// <summary>
/// 当前类中字段或者属性射影
/// </summary>
/// <returns></returns>
private Dictionary<string, Action<object>> GetSerializableData()
{
return new Dictionary<string, Action<object>>
{
{"Age",value=>Age = (int)value},
{"Name",value=>value.ToString()}
};
} /// <summary>
/// 序列化中,字段或者属性的射影
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
private Dictionary<string, object> GetSerializedData(SerializationInfo info)
{
var serializs = info.GetEnumerator();
Dictionary<string, object> dic = new Dictionary<string, object>();
while (serializs.MoveNext())
{
dic.Add(serializs.Current.Name, serializs.Current.Value);
}
return dic;
}
}

如果新的需求,需要在建模中添加字段或者属性,我们只需要,在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. java学习系列(一)Java中的IO操作

    Java的IO流是实现输入/输出的基础,它可以方便地实现数据的输入\输出操作,在Java中把不同的输入\输出源抽象为"流",通过流的方式允许Java程序使用相同的方式来访问不同的输 ...

  2. html+css--水平居中总结(不定宽块状元素方法)(一)

    来源:http://www.imooc.com/code/6363 在实际工作中我们会遇到需要为“不定宽度的块状元素”设置居中,比如网页上的分页导航,因为分页的数量是不确定的,所以我们不能通过设置宽度 ...

  3. SharePoint - 添加图片到Survey的某一问题之上

    Survey是SharePoint常用功能之一,而曾经被用户多次问到的问题是能否在Survey的某一问题上添加图片,经过查看,SharePoint Survey不提供此方法,只得谷歌之,得一比较懒但又 ...

  4. javascript进阶-原型prototype

    一.javascript原型认识 很多编程语言都有类的概念,我们可以拿原型和类进行比较,看看它们之间的区别以及相同点在哪里. 1.类:类是一个具体事物的抽象所以类是一个抽象的东西,在面向对象中类可以用 ...

  5. 博客不再更新,已转移到自己的小站iwenku.net

    博客不再更新,已转移到自己的小站iwenku.net,欢迎访问! 博客不再更新,已转移到自己的小站iwenku.net,欢迎访问! 博客不再更新,已转移到自己的小站iwenku.net,欢迎访问! 博 ...

  6. 百度地图API 简单使用

    最近项目上需要用到百度地图进行导航,参考百度地图API完成一个例子.API地址:http://developer.baidu.com/map/jsdemo.htm#a1_2 <!DOCTYPE ...

  7. NSTimer实现读秒、倒计时等周期性操作

    self.timerSchedule = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(spin ...

  8. Javascript 日期时间超强正则表达式

    var reg = /^([0-9]{4})-((?:0[1-9]|[1-9]|1[1-2]))-((?:(?:0[1-9]|[1-9])|1[0-9]|2[0-9]|3[0-1]))$|^([0-9 ...

  9. MSSQL数据库逻辑文件名修改与查看

    逻辑文件名是什么 你用的程序连接的时候使用的是数据库名,然后你在你的数据库右击属性的时候,左上角单击"文件",可以看到,数据库名和逻辑文件名是不一样的,你可以看自己的数据库的路径下 ...

  10. redistribute_prefix

    使用分发列表和前缀列表控制路由 拓扑如下 将基本环境(ip和路由协议)配置好,所得到的各个路由表如下 R1: R2: R3: EIGRP和OSPF间的双向重分发 1.      在R2上做重分发 2. ...