Как вы можете контролировать сериализацию.NET DataContract, чтобы она использовала атрибуты XML вместо элементов?

Если у меня есть класс, помеченный как 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 но я надеюсь, что есть более простое решение.

Какой самый простой способ сделать это?

3 ответа

Решение

Вы не можете сделать это с DataContractSerializer; если вы хотите атрибуты, вы должны использовать XmlSerializer вместо. С DataContractSerializer В классе разрешено более ограниченное подмножество спецификации XML, которое повышает производительность и улучшает взаимодействие опубликованных сервисов, но дает вам гораздо меньший контроль над форматом XML.

Если вы используете сервисы WCF, взгляните на XmlSerializerFormatAttribute что позволяет использовать XmlSerializer для сериализации.

Вы можете сделать это с помощью DataContractSerializer - ответ заключается в том, чтобы самостоятельно взять на себя сериализацию Xml путем реализации интерфейса IXmlSerializable. Для поддержки только записи - вы можете оставить реализацию 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();
    }
Другие вопросы по тегам