C# 为什么反序列化会引发StackOverflow异常?
当我尝试反序列化我的FooContainer(List)时,抛出了一个错误。请看这段代码的最后一部分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
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