序列化和反序列化我们可能经常会听到,其实通俗一点的解释,序列化就是把一个对象保存到一个文件或数据库字段中去,其最终目的都是将内存中的对象持久化或者是在网络上传输。反序列化就是在适当的时候把这个文件再转化成原来的对象使用。
使用序列化的原因
a. 一个原因是将对象的状态保持在存储媒体中,以便可以在以后重新创建精确的副本。我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。
b.另一个原因是通过值将对象从一个应用程序域发送到另一个应用程序域中。例如,序列化可用于在 ASP.NET 中保存会话状态并将对象复制到 Windows 窗体的剪贴板中。远程处理还可以使用序列化通过值将对象从一个应用程序域传递到另一个应用程序域中。公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET
框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。
对象序列化有两种方式,一种方式是二进制流的方式,另外一种是XML的方式。二进制流的方式,比较快,而且占用的空间比较小。因为是直接映射序列化成0,1序列,然后存在一个二进制文件中,这个文件用记事本是打不开的,即使打开也是乱码,因为就像dll一样,是二进制。而序列化XML文件,是先转换成符合一定格式的字XML符串,存在文件中,这个文件是可以用记事本打开的。然后在传输的时候,字符串对应的ASCII码,转换成对应 0,1,最终传输到网络上。所以这样做比较绕弯,但是相对于第一种,应用更普遍。因为XML我们可以作为Log保留下来。
以上是序列化的作用以及方式,下边是其一些负面内容。
A major disadvantage is that the content of the file where you serialize an object in will be tightly coupled to your source code. If you change something in the source code of the class, then you can‘t read serialized objects that were stored with the old
version of the class anymore. 这句话是说,就是序列化相关的代码是高度耦合的,比如说,XSD内容发生了变化,那么其对应的对象也就要发生变化,这样就要变动代码。
That problem becomes a nightmare when you are writing software that‘s used by customers. Suppose that you publish version 1.1 of your program, and people have files saved with version 1.0. Now version 1.1 can‘t read those files anymore because you‘ve changed
the class. You also don‘t have any control over the exact file format.
举个例子来说,现在用Message Queue来作为企业系统集成的中间件。有A和B两个系统需要集成,A系统向某个Queue里边写入数据,B系统去读取这个Queue里边的XML消息。做法是,A系统与B系统的开发人员要事先去协商,B要说明需要什么数据,A要明白提供什么数据,然后两者规定一种XML格式,即XSD文件。A系统按照规定的格式将消息放到了Queue服务器中。此时B系统收到XML后,可以使用Linq to XML来获取相应的属性,但是这样做很繁琐。普遍做法是,根据XSD生成对应的Class载体,然后调用C#的Deserilize方法将XML反序列化成内存对象。现在问题就来了,如果A系统变了XSD,那么B系统XSD相关代码就要重写,这就是为什么说耦合性高。