【问题标题】:Deserialising a collection of inherited objects反序列化继承对象的集合
【发布时间】:2013-03-26 21:29:33
【问题描述】:

我有一个 xml 文件,其中包含一个如下所示的集合

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

我知道如果我使用一个具体的集合——即两个元素是相同的类型——在 C# 中使用标准的 XML 反序列化会很容易。不同的类型似乎使它变得更加困难。

有没有办法使用简单的 xml 反序列化来解决这个问题,还是我必须自己实现反序列化?

[为清楚起见添加] 我应该补充一点,xml 已经存在,我无法更改它。我在 xml 中接收采用上述形式的消息。一个更具体的例子是:

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

我最终想要的是一个“Cycled”和一个“Walked”对象。哦,为了让它更有趣,顺序很重要。

另外,我已经尝试在代码中使用 XmlInclude 属性,但是通过在序列化时更改 xml 可以工作(当然,除非我一直使用错误)。

【问题讨论】:

  • 您不能在单个集合实例中存储不同的类型。但也许我遗漏了一些东西,您能否提供有关 AbstractCollection 的更多详细信息?
  • 你可以在一个集合中存储不同的类型,但前提是它们是集合的子类型。 @ mike1952,“似乎让事情变得更加困难”是什么意思;你试过什么?它做了什么/以什么方式不起作用?
  • 嗨 Immortal Blue 和 mclaassen,我已经编辑了上面的问题以增加清晰度并展示我尝试过的内容 - 基本上只是使用 XmlInclude,这是序列化继承的对象集合的正常方法。我的问题是它已经序列化了。 “似乎让它变得更加困难”是我低调的说法“如果不编写我自己的反序列化器,我就无法解决它。”

标签: c# xml serialization


【解决方案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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    相关资源
    最近更新 更多