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