如果我序列化派生类,即使使用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))。 在此先感谢您的帮助,
答案 0 :(得分:2)
只有在希望通过XmlInclude属性自动反序列化任何/所有派生类时,才必须为基类型创建序列化程序。您的代码无效,因为您开始创建XmlSerializer serializer = new XmlSerializer(typeof(D));
,它是子类型的序列化程序,并且没有基类的上下文。
稍后当您尝试使用类型B的Serializer反序列化此子xml时,它会失败,因为生成的序列化Xml没有基类型的上下文。
您必须创建类型B的Serializer,以便生成的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,但附加属性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
答案 1 :(得分:0)
您需要让XmlSerializer了解所有需要反序列化的类型。
使用基类类型创建XmlSerializer,然后添加其他类型
示例:
var serializer = new XmlSerializer(typeof(B), new Type[] { typeof(D), typeof(C) });