当我尝试反序列化时,我的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);
}
}
我做错了什么?
答案 0 :(得分:2)
您似乎不了解IXmlSerializable
的用途。这意味着覆盖 XmlSerializer
的默认行为。如果您只是启动另一个XmlSerializer
来实际序列化/反序列化您的WriteXml
/ ReadXml
方法,那么是的,您将获得StackOverflowException
,因为该序列化程序将调用与完全相同的对象完全相同的WriteXml
/ ReadXml
/方法。
只是摆脱IXmlSerializable
实现,因为它实际上没有做任何事情。或者阅读这篇CP文章:
How to Implement IXmlSerializable Correctly
基本上,您应该使用Read*
或Write*
上的标准XmlReader
和XmlWriter
方法来读取或写入对象。
在XmlSerializer
或ReadXml
方法中使用WriteXml
并不一定始终错误 - 只要您使用它来序列化/反序列化一个不同的对象,它既不等于也不包含对象图中声明类型的实例。
答案 1 :(得分:2)
我有完全相同的问题:
对我而言,您的界面set
或课程IFoo
中似乎缺少Foo
。如果没有set
,则对象变为只读,并且在尝试将XML反序列化为Object时将收到StackOverflowException
。
我只是将set
添加到我的属性中,然后事情就解决了。
答案 2 :(得分:0)
我调试它以确保,但我的猜测是ReadXml
的实现是递归的。 ReadXml
调用Deserialize
,调用ReadXml
,调用Deserialize
等。
ReadXml
应该使用传入的读取器读取xml并根据Xml数据保存对象(即this
)。
来自MSDN
ReadXml方法必须使用该信息重新构建对象 这是由WriteXml方法编写的。
调用此方法时,阅读器位于开头 包装您的类型信息的元素。就是这样 在开始标记之前,表示序列化的开始 宾语。当此方法返回时,它必须已读取整个元素 从头到尾,包括其所有内容。不像 WriteXml方法,框架不处理包装元素 自动。您的实施必须这样做。没有观察 这些定位规则可能导致代码生成意外的运行时 异常或损坏的数据。
实施此方法时,您应该考虑这种可能性 恶意用户可能会提供格式正确但无效的XML 表示以禁用或以其他方式改变行为 你的申请。