繁体   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