[英]How to deserialize concrete implementation of abstract class from XML
我有一个抽象类,有几个具体的实现。 这需要序列化为XML才能发送到另一个系统 - 这很好。 但是,我还需要能够反序列化相同的XML结构。 无论我尝试什么,我似乎都无法做到这一点。 我的班级结构如下:
抽象类:
[XmlIncludeAttribute(typeof(ConcreteFooOne))]
[XmlIncludeAttribute(typeof(ConcreteFooTwo))]
[XmlIncludeAttribute(typeof(ConcreteFooThree))]
[XmlRoot(ElementName = "FooData", Namespace="http://foo.bar")]
public abstract partial class AbstractFoo
{
// Some abstract props etc.
}
具体类示例:
public partial class ConcreteFooOne : AbstractFoo
{
// Some properties, constructor etc.
}
XML根示例:
<FooData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteFooOne" RequestResponse="Request" xmlns="http://foo.bar">
仅包含XML root作为示例,因为这似乎是问题所在。 现在我可以序列化很好,但是在反序列化中,如果我通过传入抽象类型反序列化,我当然会得到一个异常,说明类型“AbstractFoo”是抽象的。 所以我只是改变了逻辑,以便将具体类型(在这种情况下为ConcreteFooOne)传递给序列化器。 现在我得到一个“http://foo.bar'>没有预料到”。 我假设这是因为序列化程序不知道根节点应该是什么?
我在抽象类上定义了根节点,因为这对于所有具体实现都是相同的。 具体类型由“RequestResponse”属性定义(或者如果存在,则xsi:type属性也可以工作,因为它给出了实际的类型名称)。 有没有办法让序列化程序获取抽象类所需的内容,或者我对此完全采用错误的方法?
在此先感谢任何人的帮助,我们将不胜感激。
将[XmlRoot(ElementName =“FooData”,Namespace =“ http://foo.bar ”)]添加到子类
这是我做的一个例子:
[XmlIncludeAttribute(typeof(ConcreteFooOne))]
[XmlIncludeAttribute(typeof(ConcreteFooTwo))]
[XmlIncludeAttribute(typeof(ConcreteFooThree))]
[XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
public abstract partial class AbstractFoo
{
// Some abstract props etc.
}
[XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
public class ConcreteFooOne : AbstractFoo
{
public int MyProp { get; set; }
}
[XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
public class ConcreteFooTwo : AbstractFoo
{
}
[XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
public class ConcreteFooThree : AbstractFoo
{
}
class Program
{
static void Main(string[] args)
{
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(AbstractFoo));
using (var stream = new FileStream("test.txt", FileMode.OpenOrCreate))
{
serializer.Serialize(stream, new ConcreteFooOne() { MyProp = 10 });
stream.Flush();
}
using (var stream = new FileStream("test.txt", FileMode.OpenOrCreate))
{
var c = serializer.Deserialize(stream);
}
}
}
这很简单,在客户端实现deserealize时,定义一个XmlSerializer
如:
XmlSerializer xs= new XmlSerializer (typeof (AbstractFoo),
new Type[] { typeof (ConcreteFooOne), typeof (ConcreteFooTwo) } );
然后你可以尝试:
//it instantiate the correct class, need a streamreader
var myclass = xs.Deserialize(reader);
if (myclass is ConcreteFooOne)
//do something
if (myclass is ConcreteFooTwo)
//do something
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.