Как можно управлять сериализацией .NET DataContract, чтобы вместо элементов использовались атрибуты XML?
-
09-09-2019 - |
Вопрос
Если у меня есть класс, отмеченный как DataContract
и несколько свойств на нем, отмеченных значком DataMember
атрибуты, я могу легко сериализовать их в XML, но это создаст вывод вроде:
<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
но я надеюсь, что есть более простое решение.
Какой самый простой способ сделать это?
Решение
Вы не можете сделать это с DataContractSerializer
;если вам нужны атрибуты, вам нужно использовать XmlSerializer
вместо.С DataContractSerializer
class разрешено более строгое подмножество спецификации XML, что повышает производительность и улучшает совместимость опубликованных сервисов, но дает вам гораздо меньший контроль над форматом XML.
Если вы используете службы WCF, взгляните на XmlSerializerFormatAttribute
что позволяет использовать XmlSerializer
для сериализации.
Другие советы
Вы можете сделать это с помощью DataContractSerializer - ответ взять на себя сериализацию Xml себя, реализуя IXmlSerializable интерфейс.Для write-only support - вы можете оставить реализация ReadXml пустой, и возвращает null для GetSchema, а затем написать реализацию 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, вы по-прежнему можете добавлять атрибуты DataContract и DataMember — DataContractSerializer будет использовать реализацию интерфейса IXmlSerializable только при написании Xml.
Я написал об этом в блоге здесь.
Вы можете конвертировать туда и обратно между атрибутами и элементами при сериализации/десериализации.Для последнего работает следующее.
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();
}