2012-05-04 95 views
1

當我嘗試反序列化我的FooContainer(List)時會拋出一個錯誤。請只看這段代碼的最後部分。爲什麼這個反序列化會拋出StackOverflow異常?

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); 
    } 
} 

我在做什麼錯?

回答

2

你似乎不明白IXmlSerializable是什麼。它的意思是覆蓋XmlSerializer的默認行爲。如果你只是旋轉另一個XmlSerializer來實際上在你的WriteXml/ReadXml方法中序列化/反序列化,那麼是的,你將得到StackOverflowException,因爲該序列化器會調用完全相同的對象來完全相同的WriteXml/ReadXml /方法。

只是擺脫那IXmlSerializable實施,因爲它實際上沒有做任何事情。或閱讀這篇文章CP:

How to Implement IXmlSerializable Correctly

基本上,你應該使用在XmlReaderXmlWriter標準Read*Write*方法來讀取或寫入的對象。

它不一定總是錯誤的使用XmlSerializer一個ReadXmlWriteXml方法中 - 只要你使用它序列化/反序列化不同對象,一個既不等於也不包含的一個實例在對象圖中聲明類型。

+0

感謝您的回答,我得到了我現在應該做的。直到現在,我的疑問是如何存儲屬性值如果是T dataType? XmlSerialization編寫每種類型的數據類型,我真的不知道如何使用XmlWriter編寫此值。 –

+0

@DarfZon:泛型和XML混合不太好。在你的具體而抽象的例子中,唯一可以確定'Foo '實際上是可序列化的方法是對你知道可序列化的'T'施加約束。現在它看起來不像'Foo ',即使做了很多事情;也許如果你更多地解釋你真正的問題是什麼(在一個新的問題中),有些人可能會幫助你理順。 – Aaronaught

0

我想調試它來確定,但我的猜測是你的執行ReadXml是遞歸的。 ReadXml呼叫Deserialize,它調用ReadXml,它調用Deserialize

ReadXml應該使用在通過讀取器讀取的xml和水合對象(即this)基於所述XML數據。

MSDN

ReadXml方法必須使用寫由WriteXml方法的信息 重建你的對象。

當調用此方法時,閱讀器位於包裝類型信息的元素的起始位置 。也就是說,在開始標記之前的 指示序列化的 對象的開始。當此方法返回時,它必須從頭到尾讀取整個元素 ,包括其所有內容。與WriteXml方法不同,框架不會自動處理包裝器元素 。您的實施必須這樣做。未能遵守 這些定位規則可能導致代碼產生意外的運行時異常或損壞的數據。

實現此方法時,你應該考慮的可能性 惡意用戶可能以禁用或以其他方式改變 您的應用程序的行爲提供了一個良好的形成,但無效的XML 表示。

2

我有完全相同的問題:

對我來說,似乎你在你的界面IFoo或類Foo失蹤set。如果沒有set,則該對象將變爲只讀,並且在嘗試將XML反序列化爲Object時,您將收到StackOverflowException

我簡單地將set添加到我的屬性,並且事情解決了它自己。

+0

右:解串器也使用setter。確保你有一個公共構造函數(不帶參數)。 – Max

相關問題