Xml序列化:使用元素的基类名序序化从同一基类派生的自定义类列表

时间:2014-05-07 14:26:16

标签: c# xml list xml-serialization derived-class

修改

我的假设犯了一个错误。我已经回答自己解释了什么是错的,以及我真正需要什么。


我在序列化不同自定义类的列表时遇到问题。它们中的每一个都继承自相同的基类,而Xml文件应该显示具有基类名称的元素。

这就是我希望我的Xml文件的样子:

<TestDataMap>
    <DataMap>
        <Item Key="BoolStatus">True</Item>
        <Item Key="IntStatus">77</Item>
    </DataMap>
</TestDataMap>

我的实际代码由基类组成:

    public class BaseItem
    {
        [XmlAttribute("Key")]
        public string Key { get; set; }
        [XmlText]
        public string Value { get; set; }
    }

和多个自定义类,例如:

    [XmlType("ItemBool")]
    public class ItemBool : BaseItem
    {
        public ItemBool()
        {
            base.Key = string.Empty;
            ValueBool = false;
        }

        [XmlIgnore]
        public bool ValueBool
        {
            get { return bool.Parse(base.Value); }
            set { base.Value = value.ToString(); }
        }
    }

    [XmlType("ItemInt")]
    public class ItemInt : BaseItem
    {
        public ItemInt()
        {
            base.Key = string.Empty;
            ValueInt = int.MinValue;
        }

        [XmlIgnore]
        public int ValueInt
        {
            get { return int.Parse(base.Value); }
            set { base.Value = value.ToString(); }
        }
    }

我需要将所有这些自定义类序列化为我的基类列表,所以我已经完成了以下操作:

    [XmlRoot("TestDataMap")]
    public class TestDataMap
    {
        public TestDataMap()
        {
            DataMap = new List<BaseItem>();
        }

        // If I use the following I've got serialization exception...
        //[XmlArrayItem("Item", typeof(ItemBool))]
        //[XmlArrayItem("Item", typeof(ItemInt))]
        [XmlArray("DataMap")]
        [XmlArrayItem("Item", typeof(BaseItem))]
        public List<BaseItem> DataMap { get; set; }
    }

要测试序列化我正在使用按钮事件:

    private void button1_Click(object sender, EventArgs e)
    {
        TestDataMap testDataMap = new TestDataMap();
        ItemBool itemBool = new ItemBool() { Key = "BoolStatus", ValueBool = true };
        ItemInt itemInt = new ItemInt() { Key = "IntStatus", ValueInt = 77 };
        testDataMap.DataMap.Add(itemBool);
        testDataMap.DataMap.Add(itemInt);

        TextWriter writer = new StreamWriter(@"c:\TempTest.xml");
        Type[] dataMapTypes = new Type[] { typeof(ItemBool), typeof(ItemInt) };
        XmlSerializer serializer = new XmlSerializer(typeof(TestDataMap), dataMapTypes);
        serializer.Serialize(writer, testDataMap);
        writer.Close();
    }

但是我获得了这样的输出:

<TestDataMap>
    <DataMap>
        <Item Key="BoolStatus" xsi:type="ItemBool">True</Item>
        <Item Key="IntStatus" xsi:type="ItemInt">77</Item>
    </DataMap>
</TestDataMap>

包含我不想展示的xsi:type信息... 我的代码出了什么问题?有关我必须更改的内容的任何建议,以获得我在问题开头时发布的Xml结构吗?

1 个答案:

答案 0 :(得分:0)

当我问这个问题时,我过于关注输出xml文件的 aesthetical 结果,而不是关心重点:自定义类的xml序列化和随后的反序列化。 即使我能够像我最初发布的那样获得完全 xml元素,那么在反序列化过程中我会遇到问题:反序列化器如何从通用<Item>元素列表中知道,哪一个是<ItemBool>,哪一个是<ItemInt>,没有任何其他细节?

考虑到这一点,我理解我所问的不是我需要的,也不是正确的xml序列化方法。

所以我已将上面发布的TestDataMap课程更改为以下内容:

[XmlRoot("TestDataMap")]
public class TestDataMap
{
    public TestDataMap()
    {
        DataMap = new List<BaseItem>();
    }

    [XmlArray("DataMap")]
    [XmlArrayItem("ItemBool", typeof("ItemBool"))]
    [XmlArrayItem("ItemInt", typeof("ItemInt"))]
    public List<BaseItem> DataMap { get; set; }
}

获取此xml输出:

<TestDataMap>
    <DataMap>
        <ItemBool Key="BoolStatus">True</ItemBool>
        <ItemInt Key="IntStatus">77</ItemInt>
    </DataMap>
</TestDataMap>

通过这种方式,反序列化器可以清楚地知道每种类型的<Item>元素的反序列化。