1

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

我究竟做错了什么?

4

3 回答 3

3

我有同样的问题:

在我看来,您set的 interfaceIFoo或 class中似乎缺少您Foo。如果没有set对象变为只读,您将StackOverflowException在尝试将 XML 反序列化为对象时收到一个。

我只是添加set了我的属性,事情就自行解决了。

于 2012-09-27T11:22:00.867 回答
2

你似乎不明白这IXmlSerializable是为了什么。它旨在覆盖. XmlSerializer如果您只是启动另一个以在您的/方法XmlSerializer中实际序列化/反序列化,那么是的,您将得到一个,因为该序列化程序将在完全相同的对象上调用完全相同的 // 方法。WriteXmlReadXmlStackOverflowExceptionWriteXmlReadXml

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

如何正确实现 IXmlSerializable

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

使用内部 a或方法不一定总是错误的- 只要您使用它来序列化/反序列化不同的对象,该对象既不等于也不包含对象图中声明类型的实例。XmlSerializerReadXmlWriteXml

于 2012-05-04T01:22:35.810 回答
0

我会对其进行调试以确保,但我的猜测是您的实现ReadXml是递归的。 ReadXml呼叫Deserialize,呼叫ReadXml,呼叫Deserialize等。

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

来自MSDN

ReadXml 方法必须使用由 WriteXml 方法写入的信息来重构您的对象。

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

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

于 2012-05-04T01:13:16.973 回答