如何控制.NET DataContract序列化,以便使用XML属性而不是元素?
如果我有一个标记为DataContract
的类和一些标记有DataMember
属性的属性,我可以很容易地将它序列化为XML,但它会创build如下输出:
<Person> <Name>John Smith</Name> <Email>john.smith@acme.com</Email> <Phone>123-123-1234</Phone> </Person>
我更喜欢的是属性,比如…
<Person Name="John Smith" Email="john.smith@acme.com" Phone="123-123-1234" />
DataMember
属性允许我控制名称和顺序,但不能将其序列化为元素还是属性。 我环顾四周,发现DataContractFormat
和IXmlSerializable
但我希望有一个更简单的解决scheme。
什么是最简单的方法来做到这一点?
你不能用DataContractSerializer
来做到这一点; 如果你想要属性,你需要使用XmlSerializer
。 通过使用DataContractSerializer
类,允许XML规范中一个更具限制性的子集,它可以提高性能,并提高已发布服务的互操作性,但却使您对XML格式的控制更less。
如果您使用WCF服务,请查看XmlSerializerFormatAttribute
,它允许您使用XmlSerializer
进行序列化。
你可以用DataContractSerializer来做到这一点 – 答案是通过实现IXmlSerializable接口来自己接pipeXml序列化。 对于只写支持 – 您可以将ReadXml的实现保留为空,并为GetSchema返回null,然后按如下所示编写WriteXml的实现:
public class MyPerson : IXmlSerializable { public string Name { get; set;} public string Email { get; set;} public string Phone { get; set;} public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { } public void WriteXml(XmlWriter writer) { writer.WriteAttributeString("name", Name); writer.WriteAttributeString("email", Email); writer.WriteAttributeString("phone", Phone); } }
如果您使用的是JSON序列化的相同types,那么您仍然可以自由地添加DataContract和DataMember属性 – DataContractSerializer仅在编写Xml时才会使用IXmlSerializable接口实现。
我在这里发表了博客。
序列化/反序列化时,可以在属性和元素之间来回转换。 以下为后者的作品。
private XmlReader AttributesToElements( Stream stream ) { var root = XElement.Load( stream ); foreach ( var element in root.Descendants() ) { foreach ( var attribute in element.Attributes() ) element.Add( new XElement( root.Name.Namespace + attribute.Name.LocalName, (string)attribute ) ); element.Attributes().Remove(); } return root.CreateReader(); }