StackOverflowException при десериализации XSD - PullRequest
0 голосов
/ 04 декабря 2011

У меня есть следующая схема, которая имеет рекурсивную категорию.Я попытался использовать Xsd2Code, чтобы сгенерировать класс для этой схемы.Когда я пытаюсь десериализовать его, я получаю исключение StackOverFlow.

В конструкции класса есть:

public category()
        {
            this.catField = new category();
            this.channelField = new List<categoryChannel>();
        }

, поэтому я предполагаю, что это происходит ТАК.

Что я делаю не так ???спасибо!

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:complexType name="category">
        <xs:sequence>
            <xs:element name="channel" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:attribute name="id" type="xs:int"/>
                </xs:complexType>
            </xs:element>
            <xs:element name="cat" type="category" minOccurs="0"/>
        </xs:sequence>          
    </xs:complexType>
    <xs:element name="MH_CategoriesTree">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="response">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="cat" type="category"/>
                        </xs:sequence>
                        <xs:attribute name="type"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

ошибка

An unhandled exception of type 'System.StackOverflowException' occurred in  XXX.dll

Ответы [ 2 ]

3 голосов
/ 04 декабря 2011

Если этот фрагмент кода является конструктором, у вас есть прямая рекурсия. Первая строка создает объект того же типа, который вызывает тот же конструктор.

1 голос
/ 05 декабря 2011

Обычно xsd2code делает неправильно (см. Ответ MizardX, почему, в конструкторе).

В качестве репродукции я использовал:

xsd foo.xsd /classes

для генерации классов (а не xsd2code), тогда следующий базовый пример работает абсолютно нормально:

using System;
using System.IO;
using System.Xml.Serialization;
static class Program
{
    static void Main()
    {
        MH_CategoriesTree root = new MH_CategoriesTree(), clone;
        root.response = new MH_CategoriesTreeResponse();
        root.response.type = "alpha";
        root.response.cat = new category
        {
            cat = new category
            {
                cat = new category
                {
                    channel = new categoryChannel[]
                    {
                       new categoryChannel { id = 123, idSpecified = true }
                    }
                },
                channel = new categoryChannel [0]
            },
            channel = new categoryChannel[]
            {
                new categoryChannel { id = 456, idSpecified = true},
                new categoryChannel { id = 789, idSpecified = true },
            }
        };

        var ser = new XmlSerializer(typeof(MH_CategoriesTree));
        string xml;
        using(var sw = new StringWriter())
        {
            ser.Serialize(sw, root);
            xml = sw.ToString();
        }
        using(var sr = new StringReader(xml))
        {
            clone = (MH_CategoriesTree) ser.Deserialize(sr);
        }
        // now write "clone" to Console, to show it all worked
        ser.Serialize(Console.Out, clone);
    }
}

Итак, варианты:

  • использовать xsd.exe, а не xsd2code
  • отправить отчет об ошибке для xsd2code
  • возможно, вручную исправить созданный xsd2code конструктор, чтобы он не создавал дочерний элемент category

Другая возможная причина рекурсии здесь проста: сделать вашу модель рекурсивной! например:

    MH_CategoriesTree root = new MH_CategoriesTree(), clone;
    root.response = new MH_CategoriesTreeResponse();
    root.response.type = "alpha";
    var cat = new category();
    cat.cat = cat;
    root.response.cat = cat; // now we have an infinite loop

, который, с остальным кодом, как указано выше, вызовет его взрыв в потоке искр:

Обнаружена круговая ссылка при сериализации объекта типа категории.

Однако рекурсивная схема сама работает просто отлично.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...