Как использовать XmlSerializer для сериализации коллекций объектов - PullRequest
4 голосов
/ 29 октября 2009

Вот шаги, которые я предпринял для работы с XmlDocument, возвращаемым сторонней DLL.

  1. Я сохранил XmlDocument как SegmentationSummary.xml.
  2. Я использовал XSD.exe для создания SegmentationSummary.xsd.
  3. Я использовал XSD.exe для создания SegmentationSummary.cs.

Вот пример SegmentationSummary.cs. Обратите внимание, что ShmResult является представлением корневого узла.

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "omitted")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "omitted", IsNullable = false)]
public partial class ShmResult
{
    private ShmResultDownloadDetail[] downloadDetailField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("DownloadDetail")]
    public ShmResultDownloadDetail[] DownloadDetail
    {
        get
        {
            return this.downloadDetailField;
        }
        set
        {
            this.downloadDetailField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "omitted")]
public partial class ShmResultDownloadDetail
{
    private string modelCodeField;

    /// <remarks/>
    public string ModelCode
    {
        get
        {
            return this.modelCodeField;
        }
        set
        {
            this.modelCodeField = value;
        }
    }
}

Теперь я хотел бы использовать это, чтобы прочитать XmlDocument и начать работать с классами в SegmentationSummary.cs. Вот код, который я написал:

private XmlDocument _document;
SegmentationSummary.ShmResult _Result;
    private void LoadXML()
    {
        XmlReader xmlRdr = new XmlNodeReader(_document);
        System.Xml.Serialization.XmlSerializer s = new System.Xml.Serialization.XmlSerializer(typeof(SegmentationSummary.ShmResult));
        _Result = (SegmentationSummary.ShmResult)s.Deserialize(xmlRdr);
    }

Когда выполняется LoadXML (), я получаю исключения из этого разнообразия:

метод испытаний SegmentationSummaryHandlerTest.TestMethod1 бросил исключение: System.InvalidOperationException: Невозможно создать временный класс (Результат = 1). ошибка CS0030: невозможно конвертировать тип 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail [] в 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail' ошибка CS0029: не может быть неявно конвертировать тип 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail' в 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail []

Теперь в FAQ по http://msdn.microsoft.com/en-us/library/ms950721.aspx говорится следующее:

В: Как мне сериализовать коллекции объекты?

A: XmlSerializer выдает исключение, когда коллекция содержит типы, которые не были объявлены конструктор XmlSerializer. Вы может:

  1. Объявите типы сериализатору, передав Type [] с типы ожидать в пределах коллекция.

    OR

  2. Реализация строго типизированной коллекции, полученной из System.Collections.CollectionBase с индексатор, соответствующий методу Add ().

Мой вопрос: что из этого является «лучшим» и как мне реализовать решение?

Ответы [ 4 ]

3 голосов
/ 04 февраля 2011

Я столкнулся с подобной проблемой.

Существует проблема с сериализацией вложенных несвязанных элементов. Вот объяснение.

Чтобы решить эту проблему, я удалил maxoccurs = "unbounded" из xsd и восстановил файл класса. После этого сериализация сработала.

1 голос
/ 29 октября 2009

Я всегда использовал вариант 2 , так что для вас может сработать что-то вроде этого:

public class ShmResult : List<ShmResultDownloadDetail> { }
0 голосов
/ 12 декабря 2013

У меня была та же проблема, что и у вас:

  1. Я сделал xsd из XML, используя xsd.exe
  2. Я сгенерировал класс (ы), используя xsd.exe и получившуюся схему из шага 1.
  3. После попытки использовать этот класс в качестве типа для конструктора XMLSerializer, я получил это сообщение об исключении (псевдо-сообщение):

System.InvalidOperationException: невозможно создать временный класс (Результат = 1). ошибка CS0030: невозможно преобразовать тип Type1 [] в тип1.

Кроме того, xsd.exe сгенерировал результирующий класс с матричными типами данных (Type [] []), и на самом деле это было моей главной задачей.

Как только я сделал конструктор XMLSerializer с массивом типов, который может быть внутри коллекции, я также изменил свой xsd-файл, удалив maxoccurs = "unbounded" из нескольких элементов в моей схеме. Процесс нового поколения дал мне новый класс. После попытки использовать вновь сгенерированный класс в XMLSerializer все было хорошо.

Поэтому я предлагаю вам объявить массив типов (типов, которые могут быть частью коллекции) и представить его конструктору XMLSerializer. Также из вашей сгенерированной схемы удалите maxoccurs = "unbounded" из определенных элементов.

0 голосов
/ 03 декабря 2010

У Microsoft есть ошибка здесь. Это вышло с 2003 года. Я знаю, что ветка старая, но другие бьют головой об этом. XSD поколение не так. В описанных выше шагах использование xsd.exe для генерации xsd из xml выглядит неправильно. Я использовал инструмент под названием Trang ( с открытым исходным кодом Java ), вы можете создать XSD с этим. Фактически, вы можете использовать несколько файлов XML для его создания. Затем используйте xsd.exe для создания файла .cs. Это сработало.

...