我想将XML反序列化为派生对象(使用基类):
第一个XML:
<?xml version="1.0"?>
<root>
<elementOne>101</elementOne>
<elementTwo>10</elementTwo>
</root>
第二个XML:
<?xml version="1.0"?>
<root>
<elementOne>101</elementOne>
<elementTwo>10</elementTwo>
<elementThree>10</elementThree>
</root>
我有以下基类:
[XmlRoot(ElementName = "root")]
public class ResponseBase
{
}
以下派生类:
public class DerivedOneClass: ResponseBase
{
[XmlElementAttribute("elementOne")]
public string ElementOne {get; set;}
[XmlElementAttribute("elementTwo")]
public string ElementTwo {get; set;}
}
public class DerivedTwoClass: ResponseBase
{
[XmlElementAttribute("elementOne")]
public string ElementOne {get; set;}
[XmlElementAttribute("elementTwo")]
public string ElementTwo {get; set;}
[XmlElementAttribute("elementThree")]
public string ElementThree {get; set;}
}
但无法使用基类反序列化,以下是代码:
(T)(new XmlSerializer(typeof(T))).Deserialize(reader);
答案 0 :(得分:2)
您需要让序列化程序了解派生类。 你有两种选择:
<强>属性强>
[XmlInclude(typeof(DerivedOneClass))]
[XmlInclude(typeof(DerivedTwoClass))]
[XmlRoot(ElementName = "root")]
public class ResponseBase
{
}
直接传递
(T)(new XmlSerializer(typeof(T),
new[]{typeof(DerivedOneClass),typeof(DerivedTwoClass)}
)).Deserialize(reader);
序列化数据时,XmlSerializer
会自动为每个项目添加xsi:Type
属性。在您的示例中,序列化程序无法知道您要反序列化的两个类中的哪一个,因此如果您不是生成XML的类,则可能需要使用XmlDocument
或类似的东西手动解析XML。
另一种方法(如果你想保留XmlSerializer
)将在解析之前手动确定类型。
private static void AddTypeDefinition(XmlDocument document)
{
const string xsiNamespaceUri = "http://www.w3.org/2001/XMLSchema-instance";
XmlNode node = document.SelectSingleNode("root");
if (node == null) return;
string type = "DerivedOneClass";
XmlNodeList nodes = node.SelectNodes("//elementThree");
if(nodes != null && nodes.Count > 0)
type = "DerivedTwoClass";
var typeAttribute = node.Attributes["type", xsiNamespaceUri];
if (typeAttribute != null) continue;
XmlAttribute attribute = document.CreateAttribute("xsi", "type", xsiNamespaceUri);
attribute.Value = type;
node.Attributes.Append(attribute);
}
可以像这样使用:
XmlSerializer serializer = new XmlSerializer(typeof(ResponseBase));
XmlDocument document = new XmlDocument();
document.Load(stream);
AddTypeDefinition(document);
XmlReader reader = new XmlNodeReader(originalDocument);
ResponseBase result = serializer.Deserialize(reader) as ResponseBase;