51

上周我花了很多时间在序列化上。在那段时间里,我发现了许多使用 BinaryFormatter 或 XmlSerializer 的示例。不幸的是,我没有找到任何全面详细说明两者之间差异的示例。

我好奇的根源在于为什么 BinaryFormatter 能够直接反序列化为接口,而 XmlSerializer 则不能。Jon Skeet在对“在运行时转换为多个(未知类型) ”的回答中提供了一个直接二进制序列化到接口的示例。Stan R.在他对“ XML Object Deserialization to Interface ”的回答中为我提供了使用 XmlSerializer 实现目标的方法。

除了 BinaryFormatter 使用二进制序列化而 XmlSerializer 使用 XML 之外,我想更全面地了解根本区别。何时使用其中一种以及每种的优缺点。

4

5 回答 5

101

二进制格式化程序能够直接反序列化为接口类型的原因是,当一个对象最初被序列化为二进制流时,包含类型和程序集信息的元数据会被对象数据卡住。这意味着当二进制格式化程序反序列化对象时,它知道它的类型,构建正确的对象,然后您可以将其转换为对象实现的接口类型。

另一方面,XML 序列化程序只是序列化为一个模式,并且只序列化对象的公共字段和值,除此之外没有类型信息(例如,类型实现的接口)。

这是一篇好文章.NET Serialization,比较了BinaryFormatterSoapFormatterXmlSerializer。我建议您查看下表,除了前面提到的序列化程序之外,还包括DataContractSerializerNetDataContractSerializerprotobuf-net

序列化比较

于 2009-07-20T16:04:45.820 回答
6

只是为了称重...

两者之间的明显区别是“二进制 vs xml”,但它确实比这更深:

  • 字段(BinaryFormatter=bf)与公共成员(通常是属性)(XmlSerializer=xs)
  • 基于类型元数据 (bf) 与基于合约 (xs)
  • 版本脆弱 (bf) 与版本容错 (xs)
  • “图”(bf)与“树”(xs)
  • .NET 特定 (bf) 与可移植 (xs)
  • 不透明(bf)与人类可读(xs)

关于为什么BinaryFormatter会变脆的讨论,请参见此处

不可能讨论哪个更大;中的所有类型元数据都BinaryFormatter可以使其更大。并且XmlSerializer可以很好地使用 gzip 等压缩。

但是,可以发挥各自的优势;例如,谷歌已经开源了他们自己的数据序列化格式“protocol buffers”。这是:

  • 基于合同
  • 便携(见实现列表
  • 版本容错
  • 基于树的
  • 不透明(虽然有工具可以在与 .proto 结合使用时显示数据)
  • 通常是“契约优先”,但一些实现允许基于反射的隐式契约

但重要的是,它是非常密集的数据(没有类型元数据、纯二进制表示、短标签、变体长度 base-7 编码等技巧),并且处理效率非常高(没有复杂的 xml 结构、没有与成员匹配的字符串等)。

我可能有点偏颇;我维护其中一个实现(包括几个适用于 C#/.NET),但您会注意到我没有链接到任何特定的实现;该格式有其自身的优点;-p

于 2009-08-16T21:02:12.890 回答
2

XML Serializer 生成 XML 和 XML Schema(隐式)。它将生成符合此模式的 XML。

一个含义是它不会序列化任何无法在 XML Schema 中描述的东西。例如,在 XML Schema 中无法区分列表和数组,因此序列化程序生成的 XML Schema 可以以任何一种方式解释。

运行时序列化(它是其中的一部分)将实际的 .NET 类型序列化到另一端BinaryFormatter,因此如果您发送.List<int>List<int>

如果对方运行.NET,这显然会更好。

于 2009-07-20T15:35:50.840 回答
1

XmlSerializer 通过读取具有公共 getter 和公共 setter(以及任何公共字段)的所有类型的属性来序列化类型。在这个意义上,XmlSerializer 序列化/反序列化实例的“公共视图”。

相比之下,二进制格式化程序通过序列化实例的“内部”(即其字段)来序列化类型。任何未标记为 [NonSerialized] 的字段都将被序列化为二进制流。类型本身必须标记为 [Serializable],任何内部字段也必须被序列化。

于 2009-07-20T15:26:59.750 回答
0

我想最重要的一个是二进制序列化可以序列化公共和私有成员,而另一个只适用于公共成员。

在这里,它在大小方面提供了这两者之间的非常有用的比较。这是一个非常重要的问题,因为您可能会将序列化对象发送到远程机器。

http://www.nablasoft.com/alkampfer/index.php/2008/10/31/binary-versus-xml-serialization-size/

于 2009-07-20T15:42:33.290 回答