Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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