2013-07-19 62 views
4

我有一個具有一些具體實現的抽象類。這需要序列化到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根爲例,因爲這似乎是問題所在。現在我可以很好地序列化,但是在反序列化中,如果通過傳入抽象類型來反序列化,我當然會得到一個異常,指出「AbstractFoo」類型是抽象的。所以我只是改變了邏輯,以便將具體類型(在這種情況下爲ConcreteFooOne)傳遞給序列化程序。現在我得到一個「http://foo.bar'>沒有預料到」。我假設這是因爲序列化程序不知道根節點應該是什麼?

我在抽象類上定義了根節點,因爲這對所有具體實現都是一樣的。具體類型由「RequestResponse」屬性定義(或者如果xsi:type屬性存在,那麼xsi:type屬性也可以工作,因爲它給出了實際的類型名稱)。有沒有辦法讓序列化程序拿起抽象類所需要的東西,還是我完全用錯誤的方法來解決這個問題?

  • 請注意,我不能更改類結構太多,因爲它基於第三方提供的一些XML模式非常接近。

在此先感謝任何人的幫助,這將不勝感激。

回答

4

添加[XmlRoot(的ElementName = 「FooData」,命名空間= 「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); 
     } 
    } 
    } 
+0

剛剛發現,這將工作,謝謝。如果我只能在抽象類上定義「XmlRoot」屬性將會很好,因爲無論任何實現如何,它總是相同的。你是否知道有什麼辦法來實現這個目標,或者我只需要在任何具體的類中保留「XmlRoot」的複製? – hdougie

+1

不,你不能只在基類中做,你可以檢查http://stackoverflow.com/questions/2076024/is-xmlrootattribute-inheritable問題的屬性 – Swift

1

它的簡單,在客戶端當你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