Почему это десериализованное вызывает меня исключение Stackru?

Когда я пытаюсь десериализовать мой FooContainer (List), я получаю сообщение об ошибке. Пожалуйста, просто посмотрите последнюю часть этого кода.

public interface IFoo
{
    object Value { get; }
}

public abstract class Foo<T> : IFoo
{
    [XmlElement("Value")]
    public T Value { get; set; }
    [XmlIgnore]
    object IFoo.Value { get { return Value; } }
}

public class FooA : Foo<string> { }
public class FooB : Foo<int> { }
public class FooC : Foo<List<Double>> { }

[XmlRoot("Foos")]
public class FooContainer : List<IFoo>, IXmlSerializable
{
    public XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(XmlReader reader)
    {
        XmlSerializer serial = new XmlSerializer(typeof(FooContainer));
        serial.Deserialize(reader);
    }

    public void WriteXml(XmlWriter writer)
    {
        ForEach(x =>
            {
                XmlSerializer serial = new XmlSerializer(x.GetType(),
            new Type[] { typeof(FooA), typeof(FooB), typeof(FooC) });
                serial.Serialize(writer, x);
            });
    }
}

class Program
{
    static void Main(string[] args)
    {
        FooContainer fooList = new FooContainer()
        {
            new FooA() { Value = "String" },
            new FooB() { Value = 2 },
            new FooC() { Value = new List<double>() {2, 3.4 } } 
        };

        XmlSerializer serializer = new XmlSerializer(fooList.GetType(),
            new Type[] { typeof(FooA), typeof(FooB), typeof(FooC) });
        System.IO.TextWriter textWriter = new System.IO.StreamWriter(@"C:\temp\movie.xml");
        serializer.Serialize(textWriter, fooList);
        textWriter.Close();

        XmlReader reader = XmlReader.Create(@"C:\temp\movie.xml");
        var a = serializer.Deserialize(reader);
    }
}

Что я делаю неправильно?

3 ответа

Решение

Вы, кажется, не понимаете, что IXmlSerializable для. Он предназначен для переопределения поведения по умолчанию XmlSerializer, Если вы просто раскрутить другой XmlSerializer на самом деле сериализовать / десериализовать в вашем WriteXml/ReadXml методы, то да, вы получите StackruException потому что этот сериализатор будет вызывать точно так же, WriteXml/ReadXml/ Метод, с которого он пришел на точно такой же объект.

Просто избавься от этого IXmlSerializable реализация, так как она на самом деле ничего не делает. Или прочитайте эту статью CP:

Как правильно реализовать IXmlSerializable

В основном, вы должны использовать стандарт Read* а также Write* методы на XmlReader или же XmlWriter читать или писать объект.

Не обязательно всегда неправильно использовать XmlSerializer внутри ReadXml или же WriteXml метод - если вы используете его для сериализации / десериализации другого объекта, который не равен ни одному из объявленных типов в графе объектов или не содержит его.

У меня была точно такая же проблема:

Мне кажется, что ты скучаешь set в вашем интерфейсе IFoo или класс Foo, Без set объект становится доступным только для чтения, и вы получите StackruException при попытке десериализации XML в объект.

Я просто добавил set на мои атрибуты, и вещь решила сама.

Я бы отладил это, чтобы убедиться, но я думаю, что ваша реализация ReadXml является рекурсивным ReadXml звонки Deserialize, который вызывает ReadXml, который вызывает Deserialize, так далее.

ReadXml следует прочитать xml, используя переданный ридер, и увлажнить объект (т.е. this) на основе данных XML.

из MSDN

Метод ReadXml должен воссоздать ваш объект, используя информацию, записанную методом WriteXml.

Когда этот метод вызывается, читатель располагается в начале элемента, который оборачивает информацию для вашего типа. То есть непосредственно перед начальным тегом, который указывает начало сериализованного объекта. Когда этот метод возвращается, он должен прочитать весь элемент от начала до конца, включая все его содержимое. В отличие от метода WriteXml, платформа не обрабатывает элемент-оболочку автоматически. Ваша реализация должна сделать это. Несоблюдение этих правил позиционирования может привести к тому, что код будет генерировать непредвиденные исключения во время выполнения или повреждать данные.

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

Другие вопросы по тегам