2017-08-04 64 views
0

我想獲取從接口繼承的對象列表並將它們序列化爲xml(JSON也可接受)。這些對象中的每一個都從相同的抽象類繼承,並且遵循相同的接口。如何序列化/反序列化從普通類繼承的對象列表並遵循同一個接口?

請參見下面的類:

public abstract class Item 
{ 
    public string Name { get; set; } 
    public int SellIn { get; set; } 
    public int Quality { get; set; } 

    public Item(string name, int sellIn, int quality) 
    { 
     Name = name; 
     SellIn = sellIn; 
     Quality = quality; 
    } 

    public virtual void UpdateQuality() 
    { 
     //Default Behaviour 
    } 
} 

//子類

public class Appreciative : Item, IItem 
{ 
    public Appreciative(string name, int sellIn, int quality) : base(name, sellIn, quality) 
    {} 

    public override void UpdateQuality() 
    { 
     //Sub class behaviour 
    } 
} 

XmlSerializer類無法確定每個類的序列化/反序列化的時候,我明白了類型爲什麼,但我期待解決這個問題。

唯一的成功到目前爲止我已經在使用它已成功序列化的數據如下ExtendedXmlSerializer:

<?xml version="1.0" encoding="utf-8"?> 
<ArrayOfIItem> 
<Depreciative type="CodingChallenge3.Internals.Items.Depreciative"> 
    <Name>+5 Dexterity Vest</Name> 
    <SellIn>9</SellIn> 
    <Quality>18</Quality> 
</Depreciative> 
<Appreciative type="CodingChallenge3.Internals.Items.Appreciative"> 
    <Name>Aged Brie</Name> 
    <SellIn>1</SellIn> 
    <Quality>1</Quality> 
</Appreciative> 
<Depreciative type="CodingChallenge3.Internals.Items.Depreciative"> 
    <Name>Elixir of the Mongoose</Name> 
    <SellIn>4</SellIn> 
    <Quality>5</Quality> 
</Depreciative> 
<Fixed type="CodingChallenge3.Internals.Items.Fixed"> 
    <Name>Sulfuras, Hand of Ragnaros</Name> 
    <SellIn>0</SellIn> 
    <Quality>80</Quality> 
</Fixed> 
<TicketEvent type="CodingChallenge3.Internals.Items.TicketEvent"> 
    <Name>Backstage passes to a TAFKAL80ETC concert</Name> 
    <SellIn>14</SellIn> 
    <Quality>20</Quality> 
</TicketEvent> 
<Depreciative type="CodingChallenge3.Internals.Items.Depreciative"> 
    <Name>Conjured Mana Cake</Name> 
    <SellIn>2</SellIn> 
    <Quality>4</Quality> 
</Depreciative> 
</ArrayOfIItem> 

的類型在type屬性指定,但ExtendededXmlSerializer失敗反序列化XML,說明空引用異常。

以下是讀取和寫入數據的存儲庫代碼。

var serializedData = new ExtendedXmlSerializer().Serialize(inventory); 
     System.IO.File.WriteAllText(PATH, serializedData); 

var inventory = new List<IItem>(); 
     if (System.IO.File.Exists(PATH)) 
     { 
      var serializedData = System.IO.File.ReadAllText(PATH); 
      inventory = new ExtendedXmlSerializer().Deserialize<List<IItem>>(serializedData); 
     } 

我已閱讀堆棧溢出的類似問題,但沒有符合我的(到目前爲止)。

編輯:堆棧跟蹤

at ExtendedXmlSerialization.ExtendedXmlSerializer.ReadXml(XElement currentNode, TypeDefinition type, Object instance) 
at ExtendedXmlSerialization.ExtendedXmlSerializer.ReadXmlArray(XElement currentNode, TypeDefinition type, Object instance) 
at ExtendedXmlSerialization.ExtendedXmlSerializer.ReadXml(XElement currentNode, TypeDefinition type, Object instance) 
at ExtendedXmlSerialization.ExtendedXmlSerializer.Deserialize(String xml, Type type) 
at ExtendedXmlSerialization.ExtendedXmlSerializer.Deserialize[T](String xml) 
+0

嗯,我希望你不會不高興;)......但有趣的是,這只是c&p或是你的抽象物品類沒有實施IItem?你能添加異常的堆棧跟蹤嗎? – Fildor

+0

我改變了抽象類來實現IItem建議,但這並沒有改變結果。現在添加堆棧跟蹤 –

+0

如果您在創建序列化程序時包含相關類型(過載[像這樣一個](https://msdn.microsoft.com/en-us/library/e5aakyae( v = vs.110).aspx)允許你指定序列化器應該處理的所有類型)。 –

回答

3

JSON也是可以接受的

我不太確定你想要什麼,但你可以在Json.Net保存類型:

using Newtonsoft.Json; 

void Main() 
{ 
    var list = new List<IItem> { 
     new Appreciative("testing", 1, 2), 
     new Unappreciative("testing", 3, 4) 
    }; 

    var json = JsonConvert.SerializeObject(list, 
      new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects }); 

    var newList = JsonConvert.DeserializeObject<List<IItem>>(json, 
      new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects }); 

    foreach (var item in newList) { 
     Console.WriteLine(item.GetType().Name); 
     Console.WriteLine(item.Quality); 
     item.UpdateQuality(); 
     Console.WriteLine(item.Quality); 
    } 
} 

public interface IItem 
{ 
    string Name { get; set; } 
    int SellIn { get; set; } 
    int Quality { get; set; } 
    void UpdateQuality(); 
} 

public abstract class Item : IItem 
{ 
    public string Name { get; set; } 
    public int SellIn { get; set; } 
    public int Quality { get; set; } 

    public Item(string name, int sellIn, int quality) 
    { 
     Name = name; 
     SellIn = sellIn; 
     Quality = quality; 
    } 

    public virtual void UpdateQuality() 
    { 
     //Default Behaviour 
    } 
} 

//Sub classes 

public class Appreciative : Item 
{ 
    public Appreciative(string name, int sellIn, int quality) 
         : base(name, sellIn, quality) 
    {} 

    public override void UpdateQuality() 
    { 
     Quality = int.MaxValue; 
    } 
} 

public class Unappreciative : Item 
{ 
    public Unappreciative(string name, int sellIn, int quality) 
         : base(name, sellIn, quality) 
    {} 

    public override void UpdateQuality() 
    { 
     Quality = int.MinValue; 
    } 
} 

輸出:

Appreciative 
2 
2147483647 
Unappreciative 
4 
-2147483648 
+0

嗯謝謝你,我會檢查一下,看看現在用這個解決方案得到我需要的結果。 –

+0

這工作完美,我更喜歡JSON,再次感謝! –

相關問題