Ошибка XmlSerializer при сериализации коллекции без корневого элемента? - PullRequest
0 голосов
/ 18 января 2010

Это немного длинный вопрос, но я сделал его как можно более кратким, поэтому, пожалуйста, потерпите меня. Мне кажется, что это ошибка в классе XmlSerializer, но прежде чем я подам ее в Microsoft, я бы хотел посмотреть, пропустил ли я что-нибудь, что вполне возможно.

Я пытаюсь сгенерировать следующий XML в качестве типичного случая, который по сути является коллекцией коллекций, но где внешняя коллекция имеет дополнительные элементы:

<Links>
  <Name />
  <Group>
    <Link />
    <Link />
  </Group>
  <Group>
    <Link />
    <Link />
  </Group>
</Links>

Классы сериализации следующие:

public class Link { }

public class Links
{
    public string Name { get; set; }

    [XmlElement("Group")]
    public Link[][] Groups { get; set; }
}

А простая тестовая программа для ее запуска выглядит следующим образом:

class Program
{
    static void Main()
    {
        var serializer = new XmlSerializer(typeof(Links));
        var links = new Links { Name = "", Groups = new[] { 
            new[] { new Link(), new Link() }, 
            new[] { new Link(), new Link() } } };
        serializer.Serialize(Console.Out, links);
    }
}

При этом используется прием с использованием XmlElement для удаления родительского узла коллекции , что должно означать, что элемент <Groups> не генерируется, и для каждого объекта, содержащегося во внешнем массиве (который будет иметь тип Link[]) должен быть выделен элемент <Group>. Однако во время выполнения это дает следующее исключение из XmlSerializer:

Невозможно создать временный класс (результат = 1). ошибка CS0030: невозможно преобразовать тип 'Link [] []' в 'Link []' ошибка CS0029: невозможно неявно преобразовать тип 'Link []' в 'Link [] []'

Я предполагаю, что сериализатор по какой-то причине пытается сгладить коллекцию и думает, что тип, содержащийся во внешнем массиве, равен Link, а не Link[], что вызывает сбой компиляции его классов сериализации как типов не совпадают.

Что ты думаешь? Это ошибка? И есть ли обходной путь для генерации XML, который я использую после XmlSerializer?

Ответы [ 3 ]

1 голос
/ 18 января 2010

Я могу получить почти такую ​​же структуру, используя атрибут XmlArrayItem:

[XmlArrayItem(ElementName = "Group", Type = typeof(Link[]))]
Link[][] Groups;

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

Что касается моих тестов, то нет способа заставить атрибут XmlElement работать с неровными массивами. Будь то ошибка или «фича», я не уверен. Я согласен, что, судя по сообщению об ошибке, это похоже на ошибку. По крайней мере, следует выбросить тот факт, что XmlElement со свойствами зубчатых массивов не поддерживается, вместо того, чтобы попытаться вставить [] в [] [].

1 голос
/ 18 января 2010

Я бы предложил написать схему XML, которая определяет синтаксис, который вы хотите иметь в своем XML, и затем генерировать соответствующий код сериализации из него с помощью инструмента генерации кода (например, MS xsd.exe). В любом случае, написание схемы - это хороший подход к проверке данных. Даже если вы не хотите использовать его позже и хотите самостоятельно поддерживать код, вы можете хотя бы взглянуть на сгенерированный код.

0 голосов
/ 18 января 2010

Насколько я вижу, проблема именно в том, что говорит ошибка.

То, как вы написали желаемый XML для класса, который вы пытаетесь сериализовать, показывает, что Group - это коллекция Links; однако он определяется как неровный массив ссылок (это массив массивов).

Я полагаю, что вы вернете его в простой массив, проблема будет решена.


Отредактировано для добавления

Если вам действительно нужен XML, который вы указали, вы можете реализовать интерфейс IXmlSerializable, создать и прочитать XML самостоятельно.

Это всегда решение, когда все работает не так, как мы ожидаем.

...