【问题标题】:What are the differences between the XmlSerializer and BinaryFormatterXmlSerializer 和 BinaryFormatter 有什么区别
【发布时间】:2010-11-12 08:33:38
【问题描述】:

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

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 好表。我总是发现缺少泛型令人讨厌的 SOAP。
    • 我认为“最佳性能”分类是错误的。二进制格式化程序是 .net 中性能最差的序列化程序(soap 格式化程序除外)。至少这是大多数基准测试所显示的:blogs.msdn.com/b/youssefm/archive/2009/07/10/…james.newtonking.com/archive/2010/01/01/…techmikael.blogspot.com/2010/01/…
    • @joniba 引用的文章我还没有点进去看,但是如果不是二进制格式化器,哪个序列化器的性能最好?
    • @ahsteele 在这个特定的列表中,首先是 Protobuf-net,然后是 DataContractSerializer
    • @joniba 最佳性能始终取决于使用情况,XML 不重用元素,因此任何具有大量共享引用的数据集在 XML 进程中都会有大量重复,这会降低性能,但使用平面对象将偏爱 XML
    【解决方案2】:

    只是为了称重......

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

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

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

    不可能讨论哪个更大; BinaryFormatter 中的所有类型元数据都可以使其更大。而XmlSerializer 可以很好地处理像 gzip 这样的压缩。

    但是,可以取长补短;例如,谷歌已经开源了他们自己的数据序列化格式“protocol buffers”。这是:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

      • 嗨,John,我只是想知道处理 List 是否不是问题,您还喜欢 BinaryFormatter 吗?
      • 没有。列表只是一个例子。两者有完全不同的用例。顺便说一句,请参阅 SoapFormatter。运行时序列化(两个格式化程序)与 XML 序列化完全不同,XML 序列化与 Data Contract 序列化非常不同。
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

        • 链接已失效且未存档。
        猜你喜欢
        • 1970-01-01
        • 2010-10-02
        • 2011-12-12
        • 2010-09-16
        • 2012-03-14
        • 2012-02-06
        • 2011-02-25
        • 2011-11-22
        • 2015-03-26
        相关资源
        最近更新 更多