DataContract XML序列化和XML属性

44

能否将这个XML反序列化为一个标记有DataContract属性的对象?

<root>
<distance units="m">1000</distance>
</root>

您可能已经看到了 "units" 属性。我不相信它被支持。或者我错了吗?

2个回答

59

这是可以实现的,但您需要通过将[XmlSerializerFormat]属性应用于DataContract来覆盖默认的序列化器。 尽管可以做到这一点,但它的性能不如默认的序列化器,因此请谨慎使用。

以下类结构将为您提供所需的结果:

using ...
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Xml.Serialization;

[DataContract]
[XmlSerializerFormat]
public class root
{
   public distance distance=new distance();
}

[DataContract]
public class distance
{
  [DataMember, XmlAttribute]
  public string units="m";

  [DataMember, XmlText]
  public int value=1000;
}

您可以使用以下代码进行测试:

root mc = new root();
XmlSerializer ser = new XmlSerializer(typeof(root));
StringWriter sw = new StringWriter();
ser.Serialize(sw, mc);
Console.WriteLine(sw.ToString());
Console.ReadKey();

输出将会是:

<?xml version="1.0" encoding="utf-16"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <distance units="m">1000</distance>
</root>

9
如果你正在寻找XmlSerializerFormat属性,你可以在System.ServiceModel命名空间中找到它:http://msdn.microsoft.com/en-us/library/system.servicemodel.xmlserializerformatattribute%28v=VS.90%29.aspx - jeffreypriebe
1
当然,这对编程来说是可行的,我也喜欢阅读文档 :) - jeffreypriebe
@GregSansom,这假设您已经添加了引用。如果您没有添加引用,则“Resolve”不会显示为选项。 - Dan Esparza
所以,这似乎是通过使用DataContract属性的混合和然后XmlAttribute属性的XmlSerialization属性来实现的,我没有意识到你可以这样做,我以为只能选择其中一个。XmlSerializer会忽略DataContract属性吗? - AaronLS
2
@AaronLS 我刚试了一下,它似乎忽略了DataContact属性。我试图设置名称[DataMember(Name = "foo")],但它未使用该名称进行序列化,而是使用声明的属性名称。 - Sinaesthetic
1
@Sinaesthetic 是的,如果您使用数据契约序列化器,您需要使用DataContract/Member属性来定义结构。如果您使用Xml序列化器,那么您需要使用Xml*属性来定义结构。 - AaronLS

33

由于性能原因,默认情况下在WCF中使用的数据合同序列化器不支持XML属性(DCS平均比XML序列化器快约10%)。

因此,如果您真的想要使用DCS,则不能使用所提供的结构-必须进行更改。

或者您需要在WCF中使用XmlSerializer,正如Greg在他的回答中所示-那也可以工作,但是您将失去DCS的性能优势(以及所有其他优点)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接