XMLSerialize Список базовых типов, вызывающих ошибку неизвестных типов

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

Я обнаружил, что моя проблема возникает, когда я добавляю тег [XmlRoot] в класс, представляющий мой корневой элемент.

[XmlRoot("EFilingBatchXML", Namespace = "www.fincen.gov/base", IsNullable = false)] public class XmlRoot

До этого список работал, и я мог использовать либо [XmlInclude] для дочерних классов, либо включать Type[] при создании XmlSerializer. Есть небольшая проблема, включая атрибут:

xsi: тип = "ребенок"

xsi: тип = "Для взрослых"

Похоже, моя проблема связана с корневым тегом, но мне нужно знать, как исключить и эти атрибуты.

Ex)

[XMLElement("Person")]
public List<Person> PersonList { get; set; }
.
.
PersonList = new List<Person>() {
    new Child(), new Adult()
};

Мне нужно, чтобы он форматировался как таковой

<root>
...
    <Person>
        <Person elements>
        <Child elements>
    </Person>
    <Person>
        <Person elements>
        <Adult elements>
    </Person>
...
</root>

Я всегда получаю ошибку

Ребенка не ждали. Используйте атрибут XmlInclude или SoapInclude, чтобы указать типы, неизвестные статически.

Буду признателен за любую помощь, поскольку у меня заканчиваются идеи, и я понятия не имею, почему решение Type[] не работает для этого.


person Omen_20    schedule 02.04.2018    source источник
comment
Чтобы получить узел для каждого элемента; используйте [XmlElement] вместо [XmlArray]   -  person Marc Gravell    schedule 02.04.2018
comment
Метод Net для сериализации предполагает одну запись в корне. вот почему наличие массива Person дает ошибку. Наличие одного элемента Person в корне не приводит к ошибке.   -  person jdweng    schedule 03.04.2018
comment
@MarcGravell да, я зашел так далеко с использованием [XmlElement], но я не могу добавить дочерние классы в список, не получая ошибки. Спасибо   -  person Omen_20    schedule 03.04.2018
comment
@jdweng Элемент Person не является корневым, я просто не включил всю структуру. Мой конфликт заключается в том, что мой базовый класс List, который содержит производные дочерние элементы, дает сбой во время выполнения, потому что он говорит, что не знает о дочерних классах. Ничто из того, что я пробовал, не исправляет это. Спасибо   -  person Omen_20    schedule 03.04.2018
comment
Похоже, вы пытаетесь десериализовать иерархию полиморфных типов, где Person имеет подклассы Child и Adult. Если это так, то это похоже на дубликат Использование XmlSerializer для сериализации производных классов. Как показано здесь, вы должны применить [XmlElement("Child", Type = typeof(Child))] к своему списку. Но если это не сработает для вас, нам нужно будет увидеть минимально воспроизводимый пример, показывающий ваши Person, Child и Adult типов, а также полный необходимый XML.   -  person dbc    schedule 03.04.2018
comment
@dbc Этот поток приближает меня, но, как и в примере с XmlArray, сериализация не позволит мне определить каждого из них с одним и тем же именем «Person». Я получаю еще одно исключение InvalidOperationException, говорящее о том, что XML-элемент Person уже присутствует в текущей области. Есть ли способ или атрибут, который я могу использовать, чтобы заставить его игнорировать это? В этом потоке упоминается использование атрибута XmlInclude для абстрактного класса Person, но в моем случае это совсем не помогло.   -  person Omen_20    schedule 03.04.2018
comment
@Omen_20 - тогда, чтобы помочь вам в дальнейшем, нам нужно, чтобы вы отредактировали свой вопрос и включили минимальный воспроизводимый пример, воспроизводящий проблему. Я не уверен, что понимаю вашу проблему только из этой ветки комментариев.   -  person dbc    schedule 03.04.2018
comment
@dbc Я отредактировал вопрос.   -  person Omen_20    schedule 03.04.2018


Ответы (1)


Попробуйте следующее:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            Root root = new Root() {
                PersonList = new List<Person>() {
                    new Person() {
                        person = "Person1",
                        child = "Child1"
                    },
                    new Person() {
                        person = "Person2",
                        adult = "Adult2"
                    }
                }
            };

            XmlSerializer serializer = new XmlSerializer(typeof(Root));
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create(FILENAME,settings);
            serializer.Serialize(writer, root);
        }
    }
    public class Root
    {
        [XmlElement("Person")]
        public List<Person> PersonList { get; set; }

    }
    public class Person
    {
        [XmlElement("Person")]
        public string person { get; set; }

        [XmlElement("Child")]
        public string child { get; set; }

        [XmlElement("Adult")]
        public string adult { get; set; }
    }
}
person jdweng    schedule 02.04.2018