如何序列化/反序列化从公共类继承并遵循同一接口的对象列表?



我想获取从接口继承的对象列表,并将它们序列化为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序列化程序,它已成功序列化数据,如下所示:

<?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 属性中指定,但扩展的 XmlSerializer 无法反序列化 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)

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

最新更新