XmlSerializer和BinaryFormatter之间有什么区别

时间:2009-07-20 15:18:40

标签: c# .net serialization xml-serialization binary-serialization

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

我的好奇心的起源在于为什么BinaryFormatter能够直接反序列化到接口而XmlSerializer不能。 Jon Skeet回答“casting to multiple (unknown types) at runtime”提供了直接二进制序列化到接口的示例。 Stan R.在“XML Object Deserialization to Interface的答案中使用XmlSerializer为我提供了实现目标的方法。”

除了明显的BinaryFormatter利用二进制序列化,而XmlSerializer使用XML我想更全面地理解基本差异。何时使用其中一种或各自的利弊。

5 个答案:

答案 0 :(得分:92)

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

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

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

Serialization Comparison

答案 1 :(得分:6)

只是为了权衡...

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

  • 字段(BinaryFormatter = bf)与公开成员(通常是属性)(XmlSerializer = xs)
  • 基于类型元数据(bf)与基于合同(xs)
  • version-brittle(bf)vs版本容忍(xs)
  • “graph”(bf)vs“tree”(xs)
  • .NET特定(bf)与便携式(xs)
  • opaque(bf)vs human-readable(xs)

讨论为什么BinaryFormatter可能很脆弱,see here

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

但是,可以利用每个人的优势;例如,谷歌开源了他们自己的数据序列化格式,“协议缓冲区”。这是:

  • 合同为基础
  • portable(请参阅list of implementations
  • 版本耐受性
  • 基于树
  • opaque(虽然有与.proto结合使用时显示数据的工具)
  • 通常为“contract first”,但有些实现允许基于反射的隐式契约

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

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

答案 2 :(得分:2)

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

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

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

如果另一方运行.NET,那显然会更好。

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

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

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

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