簡體   English   中英

XmlSerializer.Deserialize即使使用XmlInclude也不能與基類一起使用

[英]XmlSerializer.Deserialize doesn't work with the base class even with XmlInclude

如果序列化派生類,則即使具有XmlInclude屬性,也無法反序列化基類。 失敗,顯示“未預期”。 如果使用與序列化數據相同的序列化程序實例,則它可以工作。 如果我創建一個新的序列化器(就像它在另一個進程中一樣),它將失敗。

    [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))。 在此先感謝您的幫助,

僅當要通過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" />

注意 :Node本身現在是B,但是附加屬性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

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

使用基類類型創建XmlSerializer,然后添加其他類型

例:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM