C# 为什么反序列化会引发StackOverflow异常?

C# 为什么反序列化会引发StackOverflow异常?,c#,xml,xml-serialization,xmlserializer,ixmlserializable,C#,Xml,Xml Serialization,Xmlserializer,Ixmlserializable,当我尝试反序列化我的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

当我尝试反序列化我的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);
    }
}
公共接口IFoo
{
对象值{get;}
}
公共抽象类Foo:IFoo
{
[XmlElement(“值”)]
公共T值{get;set;}
[XmlIgnore]
对象IFoo.Value{get{return Value;}}
}
公共类FooA:Foo{}
公共类FooB:Foo{}
公共类FooC:Foo{}
[XmlRoot(“Foos”)]
公共类FooContainer:列表,IXmlSerializable
{
公共XmlSchema GetSchema()
{
抛出新的NotImplementedException();
}
公共void ReadXml(XmlReader)
{
XmlSerializer serial=新的XmlSerializer(typeof(FooContainer));
串行。反序列化(读卡器);
}
public void WriteXml(XmlWriter)
{
ForEach(x=>
{
XmlSerializer serial=新的XmlSerializer(x.GetType(),
新类型【】{typeof(FooA)、typeof(FooB)、typeof(FooC)};
serial.Serialize(writer,x);
});
}
}
班级计划
{
静态void Main(字符串[]参数)
{
FooContainer傻瓜列表=新建FooContainer()
{
新的FooA(){Value=“String”},
新的FooB(){Value=2},
new FooC(){Value=new List(){2,3.4}
};
XmlSerializer serializer=新的XmlSerializer(doulist.GetType(),
新类型【】{typeof(FooA)、typeof(FooB)、typeof(FooC)};
System.IO.TextWriter TextWriter=new System.IO.StreamWriter(@“C:\temp\movie.xml”);
serializer.Serialize(文本编写器、傻瓜);
textWriter.Close();
XmlReader=XmlReader.Create(@“C:\temp\movie.xml”);
var a=序列化程序。反序列化(读取器);
}
}

我做错了什么?

我会调试它以确保,但我猜您的
ReadXml
实现是递归的
ReadXml
调用
反序列化
,它调用
ReadXml
,它调用
反序列化
,等等

ReadXml
应使用传入的读取器读取xml,并基于xml数据对对象(即
this
)进行水合物化

ReadXml方法必须使用这些信息重新构造对象 这是由WriteXml方法编写的

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

实现此方法时,应考虑可能性。 恶意用户可能提供格式正确但无效的XML 表示以禁用或以其他方式更改 你的申请


我会调试它以确保,但我猜您的
ReadXml
实现是递归的
ReadXml
调用
反序列化
,它调用
ReadXml
,它调用
反序列化
,等等

ReadXml
应使用传入的读取器读取xml,并基于xml数据对对象(即
this
)进行水合物化

ReadXml方法必须使用这些信息重新构造对象 这是由WriteXml方法编写的

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

实现此方法时,应考虑可能性。 恶意用户可能提供格式正确但无效的XML 表示以禁用或以其他方式更改 你的申请


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

只要去掉这个
IXmlSerializable
实现,因为它实际上什么都不做。或者阅读这篇CP文章:

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


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

您似乎不明白
IXmlSerializable
的作用。它用于覆盖
XmlSerializer
的默认行为。如果您只是启动另一个
XmlSerializer
来实际序列化/反序列化您的
WriteXml