C # Xml-Сериализация абстрактного базового типа в производный тип - какое определение свойства TypeName выигрывает?

1

Мой сценарий:

У меня есть объект, который я определил со свойствами, которые украшены тегами XmlElement и которые имеют типы, которые я определил, некоторые из которых набираются как абстрактные, которые устанавливаются в соответствующие производные типы. Я хочу, чтобы сериализовать весь этот объект в XML с помощью XmlSerializer, и все свойства, которые являются абстрактными, должны быть сериализованы как элементы с TypeName, установленными в TypeName производного типа.

Это пример того, как объекты структурированы:

[XmlType(TypeName = "MAINOBJECT")]
public class MainObject
{
    [XmlElement(Type = typeof(DerivedClass))]
    public BaseClass TheBase { get; set; }
}

[XmlInclude(typeof(DerivedClass))]
public abstract class BaseClass
{
    [XmlAttribute("AnAttribute")]
    public string AnAttribute { get; set; }

    [XmlElement("ANELEMENT")]
    public string AnElement { get; set; }

}

[XmlType(TypeName = "DERIVEDCLASS")]
public class DerivedClass : BaseClass
{
    [XmlElement("ANOTHERELEMENT")]
    public string AnotherElement { get; set; }

}

Обратите внимание, однако, что когда я создаю новый экземпляр MainObject, заполняю его свойства и сериализую его, это выглядит так:

<MAINOBJECT>
    <BaseClass AnAttribute="">
            <ANELEMENT/>
            <ANOTHERELEMENT/>
    </BaseClass>
</MAINOBJECT>

Я хочу, чтобы это:

<MAINOBJECT>
    <DERIVEDCLASS AnAttribute="">
            <ANELEMENT/>
            <ANOTHERELEMENT/>
    </DERIVEDCLASS>
</MAINOBJECT>

Вы знаете, что я делаю неправильно здесь?

Теги:
derived-class
abstract-base-class
xml-serialization

3 ответа

1
Лучший ответ

Добавьте имя XmlElement в TheBase в MainObject следующим образом:

[XmlType(TypeName = "MAINOBJECT")]
public class MainObject
{
    [XmlElement("DERIVEDCLASS", Type = typeof(DerivedClass))]
    public BaseClass TheBase { get; set; }
}
  • 0
    Поймите, что я не хочу жестко кодировать имя элемента, я хочу, чтобы он динамически выбирал любой класс, производный от BaseClass, который я назначаю для TheBase, в качестве его TypeName.
  • 0
    Это не то, как работает сериализация, потому что, если существует несколько свойств одного типа, невозможно было бы их различить. Например, public BaseClass TheBase и public BaseClass TheBase2 .
Показать ещё 5 комментариев
1

Мне кажется, что лучшим решением здесь будет реализация интерфейса IXmlSerializable, чтобы вы могли полностью контролировать, как объекты становятся сериализованными. Конечно, это больше работает, но если у вас есть такие требования, которые несколько отличаются от обычных, то вы также можете столкнуться с дополнительными причудами, где стандартный XmlSerializer не будет работать для вас по дороге.

Здесь есть хороший учебник: как правильно реализовать IXmlSerializable

Кроме того, здесь есть хорошая информация: Правильный способ реализации IXmlSerializable?

  • 0
    Сейчас я собираюсь исследовать использование IXmlSerializable, я отмечу это как правильный ответ, если смогу заставить мою реализацию работать. Спасибо!
0

Возможно, это не лучшее решение, но:

class Program
    {
        static void Main(string[] args)
        {
            XmlAttributes attrs = new XmlAttributes();

            XmlElementAttribute attr = new XmlElementAttribute();
            attr.ElementName = "DerivedClass";
            attr.Type = typeof(DerivedClass);

            attrs.XmlElements.Add(attr);

            XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();

            attrOverrides.Add(typeof(MainObject), "TheBase", attrs);

            XmlSerializer s = new XmlSerializer(typeof(MainObject), attrOverrides);

            StringWriter writer = new StringWriter();

            MainObject mo = new MainObject { TheBase = new DerivedClass { AnAttribute = "AnAttribute", AnElement = "AnElement", AnotherElement = "AotherElement" } };

            s.Serialize(writer, mo);
            Console.Write(writer.ToString());
        }
    }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню