2013-03-25 49 views
0

我有一個集合,它看起來像這樣Deserialising繼承對象的集合

<AbstractCollection> 
    <ConcreteA name="Bob" age="4"/> 
    <ConcreteB name="Tree" size="1" /> 
</AbstractCollection> 

我知道,如果我用一個具體的集合的XML文件 - 即兩個元素是同一類型 - 它很容易在C#中使用標準的XML反序列化。不同的類型似乎使它更加困難。

有沒有辦法使用簡單的xml反序列化來解決這個問題,還是我必須自己實現反序列化?

[爲了清晰起見] 我應該補充說,XML已經存在,我不能改變它。我正在接收xml中的消息,其格式如上所示。一個更具體的例子是:

<Actions> 
    <Walked name="Bob" distance="4"/> 
    <Cycled name="Jane" gear="3rd" /> 
</Actions> 

我想最終是一個「騎自行車」和「走」的對象。噢,爲了讓它變得更有趣,順序非常重要。另外,我已經嘗試在代碼中使用XmlInclude屬性,但通過更改xml當你連載它(除非我一直在使用它錯誤當然)的作品。

+0

你不能存儲在一個單一的集合實例不同的類型。但是也許我錯過了一些東西,你能否在AbstractCollection上提供更多細節? – mclaassen 2013-03-25 19:12:07

+0

您可以將不同類型存儲在單個集合中,但前提是它們是集合的子類型。 @ mike1952,你是什麼意思「似乎使它更難」;你有什麼嘗試?它做了什麼/以什麼方式不起作用? – 2013-03-25 19:28:51

+0

嗨不朽藍色和mclaassen,我已經編輯了上面的問題,以增加清晰度,並顯示我試過 - 基本上只是使用XmlInclude,這是序列化繼承的對象集合的正常方式。我的問題是它已經被序列化了。 「似乎讓它變得更加困難」是我低調的說法:「如果不編寫我自己的解串器,我就無法解決問題。」 – mike1952 2013-03-26 08:38:22

回答

1

所以我找到了解決方案,感謝this answer

關鍵是要用XmlElementAttribute來改變不同類被序列化的方式。

唯一奇怪的部分是我發現我不得不爲列表創建包裝類,否則Cycled和Walked元素不會包裝在根元素中。

我知道命名空間的東西仍然存在,但我可以處理 - 獲取派生類的問題已得到解決!

謝謝大家誰插話。

[Serializable] 
public class Actions 
{ 
    [XmlElementAttribute("Walked", typeof(WalkedAction))] 
    [XmlElementAttribute("Cycled", typeof(CycledAction))] 
    public List<Action> ActionList { get; set; } 
} 
[Serializable] 
public abstract class Action 
{ 
    [XmlAttribute] 
    public string Name { get; set; } 
} 

[Serializable] 
public class WalkedAction : Action 
{ 
    [XmlAttribute] 
    public int Distance { get; set; } 
} 

[Serializable] 
public class CycledAction : Action 
{ 
    [XmlAttribute] 
    public string Gear { get; set; } 
} 


public class Program 
{ 
    public static void Main(string[] args) 
    { 
     var actionList = new Actions(); 
     actionList.ActionList = new List<Action>(); 
     actionList.ActionList.Add(new WalkedAction { Name = "Bob", Distance = 4 }); 
     actionList.ActionList.Add(new CycledAction { Name = "Jane", Gear = "3rd" }); 

     var ser = new XmlSerializer(typeof(Actions)); 

     TextWriter w = new StringWriter(); 
     ser.Serialize(w, actionList); 

     TextReader r = new StringReader(w.ToString()); 
     Actions result = (Actions) ser.Deserialize(r); 
    } 
}