使用XmlSerializer反序列化具有额外属性的列表

4
我想要反序列化以下XML...
<MyType>
    <Items>
        <ItemSum>
            <Value>3</Value>
        </ItemSum>
        <Item>
            <Value>1</Value>
        </Item>
        <Item>
            <Value>2</Value>
        </Item>
    </Items>
</MyType>

将其转换为以下结构类型...

[XmlRoot("MyType")]
public class MyType
{
    [XmlArray("Items")]
    [XmlArrayItem("Item")]
    public CItems Items { get; set; }

    public class CItems : List<CItem>
    {
        [XmlElement("ItemSum")]
        public CItem ItemSum { get; set; }
    }

    public class CItem
    {
        [XmlElement("Value")]
        public int Value { get; set; }
    }
}

然而,如果我尝试使用C#的XmlSerializer这样做,ItemSum属性总是null。您有什么想法我做错了什么吗?


为什么你在MyType类中有CItemCItems两个类? - Rui Jarimba
@RuiJarimba:没有特别的原因。无论放在哪里都没有影响。 - Good Night Nerd Pride
规范中有些问题。你想要得到什么?XML似乎有问题,我认为在<Items>元素中你只应该有<Item>元素。 <ItemSum>应该放在<Items>之外吗? - misha
@misha:我知道这有点奇怪,但我正在处理无法指定模式的XML数据。也就是说,考虑到XML定义是不可更改的,但如果必要的话,可以对MyType的结构进行更改。 - Good Night Nerd Pride
1个回答

2

这是它:

public class MyType
{
    [XmlArray("Items")]
    [XmlArrayItem("ItemSum", typeof(ItemSum))]
    [XmlArrayItem("Item", typeof(SimpleItem))]
    public CItems Items { get; set; }

    public class CItems : List<Item> {}

    public class ItemSum : Item {}

    public class SimpleItem : Item {}

    public class Item
    {
        public int Value { get; set; }
    }
}

这样,ItemSum 就成为列表的一个元素,您可以通过检查其类型来确定它是哪个元素。

编辑:您还可以利用计算属性:

public class CItems : List<Item>
{
    [XmlIgnore]
    public ItemSum ItemSum
    {
        get { return this.OfType<ItemSum>().Single(); }
    }

    [XmlIgnore]
    public IEnumerable<SimpleItem> SimpleItems
    {
        get { return this.OfType<SimpleItem>(); }
    }
}

不错的解决方法。但我更愿意将ItemSum作为一个单独的属性。如果没有更好的答案出现,我会将你的答案标记为已接受。 - Good Night Nerd Pride
我稍微修改了一下你的答案,以得到更加通用的解决方案。感谢你提供计算属性的提示! - Good Night Nerd Pride

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接