Linq to Xml VS XmlSerializer VS DataContractSerializer

时间:2012-06-22 06:35:37

标签: serialization .net-4.0 xml-serialization linq-to-xml datacontractserializer

在我的web method中,我得到了一些第三方C#实体类的对象。实体类只是DataContract。这个实体类非常复杂,具有各种类型的属性,一些属性也是集合。当然,这些链接类型也是DataContracts。

我希望将该DataContract实体序列化为XML ,作为我的Web服务的业务逻辑的一部分。 我不能直接使用DataContractSerializer(在我在Web方法中收到的对象),因为XML模式完全不同。因此,DataContractSerializer生成的XML不会针对模式进行验证。

我无法总结出我应该遵循的方法来实施。我可以想到以下实施方法:

  1. LINQ to XML - 这看起来不错但我需要为每种类型的对象手动创建XML树(即类实例的元素或XML表示)。由于有许多实体类并且它们彼此链接,我认为手动编写XML元素太多了。此外,当实体类引入一些新属性时,我将不得不继续修改XML树。 不仅如此,我生成XML树的代码看起来有点笨拙(至少在外观上),并且将来很难被其他开发人员维护/更改;他/她将不得不仔细研究它以了解如何生成XML。

  2. XmlSerializer - 我可以编写自己的实体类来表示我想要的XML结构。现在,我需要将传入对象的详细信息复制到我自己的类的对象中。 所以这是额外的工作(对于.NET,当代码执行时也是如此!)。然后我可以在我的对象上使用XmlSerializer来生成XML。在这种情况下,我将不得不创建实体类,每当第三方实体被修改时,我只需要在我的类中添加新属性。 (使用XmlElement或XmlAttibute属性)。 但是人们建议DataContractSerializer超过这个,所以我不想最终确定这一点,除非我清楚所有方面。

  3. DataContractSerializer - 在这里,我将不得不编写自己的实体类,因为我无法控制第三方DataContracts。我需要将传入对象的细节复制到我自己的类的对象中。所以这是额外的工作。但是,由于DataContractSerializer不支持Xml属性,因此我必须实现IXmlSerializable并在WriteXml方法中生成所需的Xml。 DataContractSerializer比XmlSerializer更快,但如果第三方实体发生变化,我将不得不处理更改(在WriteXml中)。

  4. 问题:

    • 在考虑性能的情况下,哪种方法最好?
    • 你能提出一些更好的方法吗?
    • 当传入的实体类可能会发生变化时,DataContractSerializer是否值得考虑(因为它的性能优于XmlSerilaizer)?
    • LINQ应该真的用于序列化吗?或者除了查询之外的其他内容真的有用吗?
    • 在这种情况下,XmlSerializer可以优于LINQ吗?如果是,为什么?

3 个答案:

答案 0 :(得分:9)

我同意@Werner Strydom的回答。

我决定使用XmlSerializer ,因为代码变得可维护,并且它提供了我期望的性能。最重要的是它让我完全控制XML结构。

这就是我解决问题的方法:

我根据我的要求创建了实体类(表示各种类型的Xml元素),并通过XmlSerializer传递了根类(表示根元素的类)的实例。

在1:M关系的情况下小LINQ使用:

无论我想在同一个节点(比如Employee)下多次使用相同的元素(比如Department),我都声明了List<T>类型的属性。例如public List<Employee> Employees课程中的Department。在这种情况下,XmlSerializer显然在Employees节点下添加了一个名为Employee的元素(它是所有Department元素的分组)。在这种情况下,我使用LINQ在XmlSerializer序列化.NET对象之后)来操纵由XmlSerializer生成的XElement(即XML)。使用LINQ,我只需将所有Employee个节点直接放在Department节点下,然后删除Employees节点。

但是,我通过xmlSerializerLINQ的组合获得了预期的效果。

缺点是,我创建的所有课程都必须公开,因为它们很可能是内部的!

为什么不DataContractSerializerLINQ-to-XML

  • DataContractSerializer不允许使用Xml属性(除非我实现IXmlSerializable)。请参阅types supported by DataContractSerializer
  • LINQ-to-XML(以及IXmlSerializable)在创建复杂的XML结构时使代码变得笨拙,并且该代码肯定会让其他开发人员在维护/更改它时留下头脑。

还有其他办法吗?

  • 是。正如@Werner Strydom所提到的,你可以使用XSD.exe或类似Xsd2Code之类的工具生成类,如果对结果类感到满意,可以直接使用它们。

答案 1 :(得分:7)

我会选择XmlSerializer,因为它对于自定义架构来说是最易维护的(假设你有XSD)。完成系统开发后,完整地测试其性能并确定XML序列化是否导致问题。如果是,您可以用需要更多工作的东西替换它并再次测试它以查看是否有任何收益。但是,如果XML序列化不是问题,那么您就拥有可维护的代码。

与数据库或外部系统通信相比,解析一小段XML数据所需的时间可以忽略不计。在具有大内存(16GB +)的系统上,您可能会发现GC是.NET 4及更早版本中的瓶颈(.NET 4.5尝试解决此问题),尤其是在处理非常大的数据集和流时。

使用AutoMapperXSD.EXE创建的对象映射到您的实体。这将允许在不影响Web服务的情况下更改数据库设计。

关于LINQ to XML的一件好事是XSD validation。但是,这会影响绩效。

答案 2 :(得分:1)

另一种选择是利用LINQ和Reflection创建一个通用类,将对象序列化为XML。可以在http://primecoder.blogspot.com/2010/09/how-to-serialize-objects-to-xml-using.html找到一个很好的例子。我不确定你的XML在一天结束时需要看起来像什么,但如果它非常基本,这可以解决问题。您不需要在实体类添加/删除/更改属性时进行更改,并且可以在所有对象(以及存储在实用程序DLL中的其他项目)中使用它。