XML-сериализация объектов с оболочкой в C#

#c# #xml #serialization #xml-serialization

#c# #xml #сериализация #xml-сериализация

Вопрос:

Мне нужно сериализовать объекты в XML в C #. Объекты должны быть завернуты в конверт. Для этого я создал следующий Envelope класс:

 [XmlInclude(typeof(Person))]
public class Envelope
{
    public string SomeValue { get; set; }
    public object WrappedObject { get; set; }
}
  

Я использую следующий код для сериализации класса:

 string fileName = ...;
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
TextWriter textWriter = new StreamWriter(fileName);
try
{
    serializer.Serialize(textWriter, <instance of envelope>);
}
finally
{
    textWriter.Close();
}
  

Когда я присваиваю объекту типа Person to WrappedObject , я получаю следующий XML:

 <Envelope>
    <SomeValue>...</SomeValue>
    <WrappedObject xsi:type="Person">
        ....
    </WrappedObject>
</Envelope>
  

Проблема в том, что я хотел бы, чтобы тег для обернутого объекта был назван в честь фактического класса, в который я передаю. Например, если я назначу экземпляр Person для WrappedObject , я бы хотел, чтобы XML выглядел следующим образом:

 <Envelope>
    <SomeValue>...</SomeValue>
    <Person>
        ....
    </Person>
</Envelope>
  

Если я назначу экземпляр Animal , я хотел бы получить

 <Envelope>
    <SomeValue>...</SomeValue>
    <Animal>
        ....
    </Animal>
</Envelope>
  

Как бы мне этого добиться?

Редактировать

На самом деле я немного упростил свой пример… Обернутый объект фактически снова оборачивается:

 public class Envelope
{
    public string SomeValue { get; set; }
    public Wrapper Wrap { get; set; }
}

[XmlInclude(typeof(Person))]
public class Wrapper
{
    public object WrappedObject { get; set; }
}
  

Как бы я справился с этим, используя переопределение атрибутов?

Ответ №1:

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

Это грубый непроверенный фрагмент, но он должен указать вам правильное направление:

 XmlAttributes attributes = new XmlAttributes();
XmlAttributeOverrides xmlAttributeOverrides = new XmlAttributeOverrides();
attributes.XmlElements.Add(new XmlElementAttribute("Person", t));
xmlAttributeOverrides.Add(typeof(Person), "WrappedObject", attributes);
XmlSerializer myserialiser = new XmlSerializer(typeof(Envelope), xmlAttributeOverrides);
  

Комментарии:

1. Хорошо, я вижу, как это работает, но я должен признать, что я немного упростил свой пример 😉 Не могли бы вы взглянуть на мою измененную версию выше?

2. Должен работать тот же код. Вам даже не понадобится XmlInclude

3. Хм, когда я удаляю XmlInclude , я получаю исключение, в котором говорится что-то вроде «Неожиданный тип …, используйте XmlInclude или SoapInclude …».

4. Хорошо, возможно, вы можете добавить, XmlInclude используя XmlAttributeOverrides сам и сделать его аккуратнее.

5. Упс, я скопировал / вставил ваш код, и после имени свойства есть дополнительный символ «Пробел» WrappedObject . Я случайно оставил это в. Когда я удаляю его, все работает так, как ожидалось! Большое вам спасибо!