2015-10-29 100 views
1

如果我序列化派生類,即使使用XmlInclude屬性,我也無法反序列化基類。它因「沒有預料到」而失敗。如果我使用與序列化數據相同的序列化程序實例,它將起作用。如果我創建了一個新的序列化程序(就像它在另一個進程中一樣),它會失敗。即使使用XmlInclude,XmlSerializer.Deserialize也不能與基類一起工作

[Serializable] 
    [XmlInclude(typeof(D))] 
    public class B 
    { 
     public string x { get; set; } 
    } 
    public class D : B 
    { 
     public string y { get; set; } 
    } 

... code snippet .... 
    D x = new D(); 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(D)); 
     serializer.Serialize(ms, x); 
     ms.Flush(); 

     ms.Seek(0, SeekOrigin.Begin); 
     string responseBuffer = Encoding.ASCII.GetString(ms.GetBuffer()); 

     ms.Seek(0, SeekOrigin.Begin); 
     serializer = new XmlSerializer(typeof(B)); 
     B x2 = (B)serializer.Deserialize(ms); 
    } 

正如我前面提到的,如果我使用原始序列化程序(typeof(D))它的工作原理。如果我重新創建串行器(typeof(B))。 在此先感謝您的幫助,

+0

你可以看看這裏 http://stackoverflow.com/questions/12237268/how-to-implement-xml-serialization-with -inherited-class-in-c-sharp – Darshana

回答

2

你必須創建只有當你要反序列化的任何/所有的基本類型串行派生類自動通過XmlInclude屬性。你的代碼不起作用,因爲你首先創建XmlSerializer serializer = new XmlSerializer(typeof(D));這是一個子類型的序列化器,並且沒有基類的上下文。

當您嘗試使用類型B的序列化程序對此子級xml進行反序列化時,它會失敗,因爲生成的序列化Xml沒有基本類型的上下文。

您必須創建類型B的串行器,以便生成的Xml具有屬性xsi:type,該屬性指示XmlSerializer在反序列化期間實例化哪個子類型。

你的代碼改成這樣:從你剛纔的代碼

using (MemoryStream ms = new MemoryStream()) 
{ 
     XmlSerializer serializer = new XmlSerializer(typeof(B)); 
     serializer.Serialize(ms, x); 
     ms.Flush(); 

     ms.Seek(0, SeekOrigin.Begin); 
     string responseBuffer = Encoding.ASCII.GetString(ms.GetBuffer()); 

     ms.Seek(0, SeekOrigin.Begin); 
     serializer = new XmlSerializer(typeof(B)); 
     B x2 = (B)serializer.Deserialize(ms); 
} 

的Xml看起來像:

<D xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" /> 

然而,上面貼的代碼會產生下面的XML:

<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="D" /> 

注意:節點本身現在是B,但廣告ditional屬性xsi:type =「D」告訴XmlSerializer什麼是實際類型。這適用於您在父節點中包含XmlInclude屬性。

此外,爲生成/序列化xml到字符串MemoryStream類型是不需要的。通過ASCII GetString轉換並不理想。您可以使用的StringWriter和StringReader

你可以把它簡化

D x = new D(); 
string xml; 
using(var sw = new StringWriter()) 
{ 
    var serializer = new XmlSerializer(typeof(B)); 
    serializer.Serialize(sw, x); 
    xml = sw.ToString(); 
} 

B x2; 
using(var sr = new StringReader(xml)) 
{ 
    var serializer = new XmlSerializer(typeof(B)); 
    x2 = serializer.Deserialize(sr) as B; 
} 
// if you check instance of x2 in debug, it will be of type D 
+0

感謝您解釋發生了什麼事。它工作完美! – Kevin

0

您將需要讓XmlSerializer知道所有需要反序列化的類型。

與基類創建XmlSerializer的,然後添加其他類型的

例子:

var serializer = new XmlSerializer(typeof(B), new Type[] { typeof(D), typeof(C) }); 
+0

XmlInclude元素給我帶來了什麼?我原以爲自從我傳入基類後,XmlSerializer就會從基類中取出屬性並完成上面的語法。 – Kevin

相關問題