反序列化继承对象的集合

时间:2013-03-25 18:56:04

标签: c# xml serialization

我有一个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起作用(除非我当然错误地使用它)。

1 个答案:

答案 0 :(得分: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);
    }
}