[英]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文章:
基本上,您应该在XmlReader
或XmlWriter
上使用标准的Read*
和Write*
方法来读取或写入对象。
在ReadXml
或WriteXml
方法中使用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.