2017-08-04 3 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クラスは、各クラスのタイプを決定することはできません、私は理由を理解するが、私は探しています問題を回避する方法、

<?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をデシリアライズに失敗:

私がこれまで持っていた唯一の成功は、次のように成功したデータをシリアライズしているExtendedXmlSerializerを使用していますnull参照例外が発生しています。

ここでは、データを読み書きするリポジトリコードを示します。

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); 
     } 

私は(これまで)鉱山に一致するスタックオーバーフローが、どれにも同様の問題を読みました。

EDIT:スタックトレース

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

シリアライザの作成時に関連する型をインクルードしていれば、これは 'XmlSerializer'で問題なく動作します(オーバーロード[このようなものです](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が好きです。もう一度感謝します! –

関連する問題