[英]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.