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

Если у меня есть класс, помеченный как a, DataContract и несколько свойств на нем, отмеченных DataMember атрибутами, я могу легко сериализовать его в XML, но он будет создавать такие выходные данные:

<Person>
    <Name>John Smith</Name>
    <Email>[email protected]</Email>
    <Phone>123-123-1234</Phone>
</Person>

Я бы предпочел атрибуты, например ...

<Person Name="John Smith" Email="[email protected]" Phone="123-123-1234" />

DataMember Атрибут позволяет мне контролировать имя и порядок , но не является ли сериализовать в качестве элемента или атрибута. Я посмотрел вокруг и нашел DataContractFormat и , IXmlSerializable но я надеюсь , там есть простое решение.

Как это сделать проще всего?

Ответов (3)

Решение

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

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

Вы можете конвертировать между атрибутами и элементами при сериализации / десериализации. Для последнего работает следующее.

    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();
    }

Вы можете сделать это с помощью 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.

Я писал об этом здесь .