Сериализация контракта данных со сложными типами

Я использую сериализацию контракта данных для сериализации следующих классов в XML:

[DataContract]
public partial class Foo
{
    [DataMember]
    public string MyString { get; set; }
    [DataMember]
    public int MyInt { get; set; }
    [DataMember]
    public Bar MyBar { get; set; }
}

[DataContract]
public class Bar
{
    public int BarId { get; set; }
    [DataMember]
    public string BarField { get; set; }
}

Когда я сериализую его, он генерирует XML следующим образом:

<Foo>
    <MyString>My text</MyString>
    <MyInt>2</MyInt>
    <MyBar>
        <BarField>My bar field</BarField>
    </MyBar>
</Foo>

Я бы хотел, чтобы поле MyBar не отображалось как сложный тип, а вместо этого:

<Foo>
    <MyString>My text</MyString>
    <MyInt>2</MyInt>
    <MyBar>My bar field</MyBar>
</Foo>

Я новичок в сериализации контрактов данных и не нашел никаких руководств по моей проблеме. Я даже не знаю, возможно это или нет, но я подумал, что спрошу, прежде чем сдаться, и разберусь с этим так, как есть, или найду лучшее решение.


person jebar8    schedule 13.11.2012    source источник


Ответы (2)


Декорируя классы данных как DataContract, вы по своей сути устанавливаете структуру (Xml, Json и т. Д.), В которой данные будут представлены в том виде, в котором они были сериализованы.

Могу ли я предложить вам разделить проблемы «Business Entity» и «Serialization Entity» из ваших классов данных, например если Foo + Bar являются вашими представлениями данных в памяти или ORM, удалите из них [DataContract]:

public partial class Foo
{
    public string MyString { get; set; }
    public int MyInt { get; set; }
    public Bar MyBar { get; set; }
}

public class Bar
{
    public string BarField { get; set; }
}

Затем предоставьте новый класс специально для сериализованного формата, украшенный DataContract

[DataContract]
public partial class SerializableFoo
{
    [DataMember]
    public string MyString { get; set; }
    [DataMember]
    public int MyInt { get; set; }
    [DataMember]
    public string MyBar { get; set; }
}

А затем предоставьте функцию сопоставления для сопоставления одного с другим. LINQ отлично подходит для такого рода работы, и если классы имеют в основном одинаковые имена свойств, AutoMapper может сделать большую часть работы за вас.

e.g.

var wireFoo = new SerializableFoo()
{
    MyString = foo.MyString,
    MyInt = foo.MyInt,
    MyBar = foo.Bar.BarField // Do the projection / flattening here
}
// Serialize wireFoo here, or return it from a WCF Service, etc.
person StuartLC    schedule 13.11.2012

Вы определяете его как сложный тип ... что означает, что он проявится как таковой. Если вы этого не хотите, измените контракт данных, чтобы Foo имел Bar как String, а не как сложный тип.

В основном, в терминах XML вы определяете свой класс как DataContract, а свои свойства как DataMembers, вы создаете свой сложный объект или элемент, содержащий элементы. В представленном вами случае вы должны изменить свой первый контракт данных, чтобы он не содержал дополнительных сложных объектов, а только те данные, которые вам нужны.

Однако при применении объектно-ориентированного проектирования в этих ситуациях SOA, в зависимости от того, что вы пытаетесь выполнить, со сложными объектами внутри других сложных объектов может быть легче работать и даже читать, чем с ОГРОМНЫМ сложным объектом, полным свойств.

Чтобы получить результат, вы должны отбросить свой класс Bar и просто получить строку в Foo.

[DataContract]
public partial class Foo
{
    [DataMember]
    public string MyString { get; set; }
    [DataMember]
    public int MyInt { get; set; }
    [DataMember]
    public string MyBar { get; set; }
}

РЕДАКТИРОВАТЬ: Я думаю, что я не был достаточно ясен в ответе: НЕТ, вы не можете получить то, что хотите, и сохранить свои сложные типы. Ваш XML будет структурирован на основе вашего объектно-ориентированного дизайна.

person iMortalitySX    schedule 13.11.2012
comment
Спасибо за ответ, но я спросил не об этом. Я спросил, можно ли реализовать нужную мне функциональность при сохранении сложных типов. Если ваше решение состоит в том, чтобы просто отказаться от сложного типа и сделать его строкой, тогда вы должны были просто сказать мне «нет». Если бы моя ситуация была такой же простой, как приведенный мною пример, это отлично сработало бы. К сожалению, это не так. - person jebar8; 13.11.2012