【问题标题】:Any reason not to use XmlSerializer?有什么理由不使用 XmlSerializer?
【发布时间】:2010-07-13 16:28:38
【问题描述】:

我刚刚了解了 .Net 中的 XmlSerializer 类。在我总是使用标准类解析和编写我的 XML 之前。在深入研究之前,我想知道是否存在不正确的选择。

编辑:标准类是指 XmlDocument、XmlElement、XmlAttribute...等。

【问题讨论】:

  • 哪些“标准课程”?这个问题需要澄清。
  • @DDavies:我相信他的意思是 XmlDocument、XmlElement、XmlAttribute 等......即符合 W3C 标准的 XML 类。

标签: c# .net xml serialization


【解决方案1】:

使用XmlSerializer时有很多限制:

  • 您必须有一个 public 无参数构造函数(正如 cmets 中的 idlewire 所述,它不必是公共的)
  • 仅对公共属性进行序列化
  • 接口类型无法序列化
  • 还有其他一些...

这些约束通常会迫使您做出某些设计决策,而这些决策在其他情况下不会做出……而迫使您做出错误设计决策的工具通常不是一件好事;)

话虽如此,当您需要一种以 XML 格式存储简单对象的快速方法时,它会非常方便。我也喜欢这样一个事实,即您可以很好地控制生成的架构。

【讨论】:

  • 请注意,无参数构造函数不必是公共的。 private 和 internal 也可以。
  • @idlewire,你是对的,我以前从未意识到这一点。但是我怀疑它只有在完全信任的情况下才能工作......
  • 反序列化将执行设置的访问器,您可能不希望这种情况发生。反序列化将访问无参数构造函数,您可能不希望这种情况发生。您为您的业务目的编写代码,您不一定希望 XmlSerializer 将相同的代码用于其目的。作为替代方案之一,DataContractSerializer 也运行 set 访问器,但至少它不需要无参数构造函数。您可以通过使用 [DataMember] 装饰私有后备存储而不是装饰属性来避免任何 setter 副作用。
【解决方案2】:

嗯,很明显,它并没有让您对输出有太多的控制。就我个人而言,我发现 LINQ to XML 使得手动编写它变得非常容易,我很高兴这样做,至少对于相当小的项目而言。如果您使用的是 .NET 3.5 或 4 但不使用 LINQ to XML,请立即查看它 - 它比旧 DOM 好得多很多

有时能够控制序列化和反序列化是件好事……尤其是当您更改数据的布局时。如果您没有遇到这种情况并且没有预料到会遇到这种情况,那么内置的 XML 序列化可能就可以了。

编辑:我不认为 XML 序列化支持构造真正不可变的类型,而这显然可以通过手工构建。由于我是不变性的粉丝,这绝对是我会担心的事情。如果您实现IXmlSerializable,我相信您可以使用 public 不变性,但您仍然必须是私有可变的。当然,我可能是错的 - 但值得检查。

【讨论】:

  • 您能否稍微澄清一下您说您是不变性的粉丝是什么意思?您处理 XML 序列化的一般策略是什么?
  • @Dmitry:我发现当我的类型是不可变的时,代码更容易推理并且多线程更简单。对于 XML 序列化,我经常手动编写自己的 ToXElement 和 FromXElement 代码。这并不难,而且您最终可以完全控制生成的内容。
【解决方案3】:

如果您经常序列化和反序列化相同的类型,并且如果您需要这些类型的序列化表示可以被不同的平台(即 Java、Javascript 等)使用,那么 XmlSerializer 可以为您省去很多麻烦。建议尽可能使用 XmlSerializer,因为它可以减轻您自己管理从对象图到 XML 的转换的大量麻烦。

在某些情况下,使用 XmlSerializer 并不是最好的方法。以下是几种情况:

  • 当您需要快速、只转发处理大量 xml 数据时
    • 改用 XmlReader
  • 当您需要使用 XPath 在 xml 文档中执行重复搜索时
  • 当 xml 文档结构比较随意,并且不符合已知的对象模型时
  • 当 XmlSerializer 强加的要求不能满足您的设计要求时:
    • 当你不能有默认的公共构造函数时不要使用它
    • 您不能使用 xml 序列化程序属性来定义元素和属性名称的 xml 变体以符合必要的 Xml 架构

【讨论】:

  • +1 用于提及大小参数和 XmlReader 作为替代
【解决方案4】:

我发现 XmlSerializer 的主要缺点是:

1) 对于涉及集合的复杂对象图,有时很难通过使用序列化控制属性来准确获取所需的 XML 模式。

2) 如果您在应用的一个版本和下一个版本之间更改类定义,您的文件将变得不可读。

【讨论】:

  • #2 是我发现很多程序员都害怕的大问题
  • 还是没有BinarySerializer那么脆
【解决方案5】:

是的,我个人使用自动 XML 序列化 - 尽管我使用 DataContractSerializer 最初是因为 WCF 而引入的(序列化没有属性的类型的能力非常有用),因为它没有在其中嵌入类型。当然,因此您需要知道在重新加载时要反序列化的对象的类型。

最大的问题是,如果不对您可能希望写入其数据的类型实现 IXmlSerializable 或公开序列化程序可以本机处理的其他类型,也很难序列化为属性。

我想最大的问题是你不能自动序列化接口,因为 DCS 希望能够在收到 XML 返回时再次构造实例。但是,本机支持标准集合接口。

不过,总而言之,我发现 DCS 路线是最快且最轻松的方式。

作为替代方案,如果您想要完全控制,您还可以研究使用 Linq to XML 来读取和写入 XML - 但您仍然必须使用此方法逐个成员处理类型。

在阅读了 Jon Skeet 新书的抢先体验后,我最近一直在研究它(像瘟疫一样避免它,因为我看不出重点)。不得不说 - 我对使用 XML 的轻松程度印象最深。

【讨论】:

    【解决方案6】:

    我过去经常使用 XmlSerializer,并且可能会继续使用它。然而,最大的陷阱是上面已经提到的一个:

    对序列化程序的约束(例如对公共成员的限制)要么 1) 对类施加与其主要功能无关的设计约束,要么 2) 强制增加解决这些约束的复杂性。

    当然,Xml序列化的其他方法也会增加复杂度。

    所以我想我的答案是,没有适合所有情况的正确或错误答案;选择序列化方法只是众多其他设计考虑因素之一。

    【讨论】:

      【解决方案7】:

      有一些场景。

      • 您必须处理大量 XML 数据 - 序列化程序可能会使您的内存过载。对于一个包含 2000 个左右表的数据库转储的简单模式,我曾经有过这种情况。只有少数几个类,但最终序列化不起作用 - 我不得不使用 SAX 流解析器。

      除此之外 - 在正常情况下我看不到任何东西。与使用较低级别的解析器相比,处理 XML 序列化程序要容易得多,尤其是对于更复杂的数据。

      【讨论】:

        【解决方案8】:

        当您想要传输大量数据并且您的资源非常有限时。

        【讨论】:

          猜你喜欢
          • 2010-09-29
          • 2013-09-27
          • 2011-11-16
          • 1970-01-01
          • 1970-01-01
          • 2020-04-08
          • 1970-01-01
          • 2010-10-11
          • 2010-10-10
          相关资源
          最近更新 更多