繁体   English   中英

为什么这个反序列化会抛出StackOverflow异常?

[英]Why this deserialized throws me StackOverflow exception?

当我尝试反序列化我的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);
    }
}

我究竟做错了什么?

您似乎不了解IXmlSerializable的用途。 它用于覆盖 XmlSerializer的默认行为。 如果您只是旋转另一个XmlSerializer来实际在WriteXml / ReadXml方法中序列化/反序列化,那么是的,您将得到一个StackOverflowException因为该序列化器将在完全相同的对象上调用完全相同的WriteXml / ReadXml /方法。

只是摆脱IXmlSerializable实现,因为它实际上没有做任何事情。 或者阅读这篇CP文章:

如何正确实现IXmlSerializable

基本上,您应该在XmlReaderXmlWriter上使用标准的Read*Write*方法来读取或写入对象。

ReadXmlWriteXml方法中使用XmlSerializer并不一定总是错误的 - 只要您使用它来序列化/反序列化另一个对象,该对象既不等于也不包含对象图中声明类型的实例。

我有同样的问题:

对我来说,似乎你在接口IFoo或类Foo中缺少set 如果没有set ,对象将变为只读,并且在尝试将XML反序列化为Object时将收到StackOverflowException

我只是将set添加到我的属性中,然后事情就解决了。

我调试它以确保,但我的猜测是你的ReadXml的实现是递归的。 ReadXml调用Deserialize ,调用ReadXml ,调用Deserialize等。

ReadXml应该使用传入的读取器读取xml并根据Xml数据水合对象(即this )。

来自MSDN

ReadXml方法必须使用WriteXml方法写入的信息重新构建对象。

调用此方法时,阅读器位于包含类型信息的元素的开头。 也就是说,就在指示序列化对象开始的开始标记之前。 当此方法返回时,它必须从头到尾读取整个元素,包括其所有内容。 与WriteXml方法不同,框架不会自动处理包装元素。 您的实施必须这样做。 如果不遵守这些定位规则,可能会导致代码生成意外的运行时异常或损坏的数据。

实现此方法时,您应该考虑恶意用户可能提供格式正确但无效的XML表示形式,以禁用或以其他方式更改应用程序的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM