什么是序列化?

序列化到底在哪里? 我读到关于网络上的序列化,我已经知道了

它是一个接口,如果在类中实现,意味着它可以被不同的序列化器自动序列化和反序列化。

给我一个很好的理由,为什么以及什么时候需要序列化一个类? 假设一旦序列化,究竟发生了什么?

只要对象需要持久化或传输超出其存在范围,就需要进行序列化。

持久性是指在某处保存对象并在以后以相同状态加载它的能力。 例如:

  • 您可能需要将对象实例作为文件的一部分存储在磁盘上。
  • 您可能需要将对象作为blob(二进制大对象)存储在数据库中。

传输是将对象发送到其原始范围之外的能力。 例如:

  • 您可能需要将对象的实例传输到远程计算机。
  • 您可能需要将实例传输到同一台计算机上的另一个AppDomain或进程。

对于其中的每一个,必须有一些串行位表示,可以存储,传送,然后用于重构原始对象。 将对象转换为这一系列位的过程称为“序列化”,而将一系列位转换为原始对象的过程称为“反序列化”。

序列化forms的对象的实际表示可能因您的目标而异。 例如,在C#中,您既有XML序列化(通过XmlSerializer类)又有二进制序列化(通过使用BinaryFormatter类)。 根据您的需要,您甚至可以编写自己的自定义序列化程序来执行其他工作,例如压缩或加密。 如果您需要语言和平台中立的序列化格式,您可以尝试Google的协议缓冲区 ,它现在支持.NET (我没有使用过它)。

上面提到的XML表示适用于以标准格式存储对象,但根据您的需要,它可能是冗长和缓慢的。 二进制表示节省了空间,但不像XML那样可以跨语言和运行时移植。 重要的是串行器和解串器必须相互理解。 当您开始引入向后和向前兼容性和版本控制时,这可能是一个问题。

潜在的序列化兼容性问题的示例:

  • 您发布了程序的1.0版,它能够将某些Foo对象序列化为文件。
  • 用户执行一些操作以将其Foo保存到文件中。
  • 您使用更新的Foo发布程序的2.0版。
  • 用户尝试使用您的2.0版程序打开版本1.0文件。

如果版本2.0 Foo具有版本1.0 Foo没有的其他属性,这可能会很麻烦。 您必须明确地不支持此方案,或者在序列化方面有一些版本控制故事。 .NET可以为您做一些这样的事情。 在这种情况下,您可能还有相反的问题:用户可能会尝试使用您的程序版本1.0打开版本2.0 Foo文件。

我自己没有使用过这些技术,但.NET 2.0及更高版本支持版本容忍序列化以支持向前和向后兼容性:

  • 容忍无关或意外的数据。 这使该类型的较新版本能够将数据发送到旧版本。
  • 容忍丢失的可选数据。 这使旧版本能够将数据发送到更新的版本。
  • 序列化回调。 这样可以在缺少数据的情况下设置智能默认值。

例如,当您想通过网络发送对象或将它们存储到文件中时。

假设您正在为video游戏创建Savegame格式。 然后你可以使类Player和每个Enemy序列化。 这样就可以很容易地将当前对象的状态保存到文件中。

另一方面,在为游戏编写多人游戏实现时,您可以将通过网络序列化的Player发送给其他客户端,然后其他客户端可以处理这些数据。

在非面向对象语言中,人们通常会将数据以字节模式存储在内存中,这些数据在没有引用任何其他内容的情况下“有意义”。 例如,图形编辑器中的一堆形状可能只是连续存储所有点。 在这样的程序中,简单地将所有数组的内容存储到磁盘可能会产生一个文件,当读回这些数组时会产生原始数据。

在面向对象语言中,许多对象存储为对其他对象的引用。 仅仅存储内存数据结构的内容将没有用,因为对对象#24601的引用将不会说明该对象代表什么。 虽然面向对象的系统可能能够很好地搞清楚内存数据“意味着什么”并尝试将其自动转换为合理的格式,但它无法识别对象引用之间的所有区别到同一个对象,以及那些指向恰好匹配的对象的对象。 因此,在将对象转换为原始比特流时,通常需要帮助系统。

不是类,但特定对象可能被序列化以存储在某个持久存储中或将对象传递到另一个应用程序/通过网络。

例如,当您想要将对象发送到某个URL时,您可能决定以xml格式发送它。 从内存中对象转换为(在本例中)xml的过程称为序列化。 从xml转换为内存中称为反序列化。