尝试将xml数组反序列化为带有子类的C#类

时间:2016-03-07 22:32:02

标签: c# xml-deserialization

我有一个简单的例子,我已经从我的真实代码中解脱了。问题是我可以在下面创建一个C#类,只要我能够在类层次结构中显式分配类型。但是,我的Panels数组并没有创建一个子类的TwoColumnPanel。相反,我只在Panels列表中获得一个面板。

[TestMethod]
    public void XmlRepoCreatesTestRepo()
    {
        object obj;
        using (XmlReader reader = XmlReader.Create(new StringReader(TestXml)))
        {
            reader.MoveToContent();
            switch (reader.Name)
            {
                case "TestRepo":
                    obj = new XmlSerializer(typeof(TestRepo)).Deserialize(reader);
                    break;
                default:
                    throw new NotSupportedException("Unexpected: " + reader.Name);
            }
        }
    }

    public string TestXml = @"<TestRepo>
                                <Name>Wandercoder Was Here</Name>
                                <Page>
                                    <Panel>
                                        <ColumnAttribute>1</ColumnAttribute>
                                    </Panel>
                                    <TwoColumnPanel>
                                        <ColumnAttribute>2</ColumnAttribute>
                                    </TwoColumnPanel>
                                    <Panels>
                                        <Panel>
                                            <ColumnAttribute>1</ColumnAttribute>
                                        </Panel>
                                        <TwoColumnPanel>
                                            <ColumnAttribute>2</ColumnAttribute>
                                        </TwoColumnPanel>
                                    </Panels>
                                </Page>
                            </TestRepo>";
}

[DataContract]
[Serializable]
public class TestRepo
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public Page Page { get; set; }
}
[DataContract]
[Serializable]
public class Page
{
    //This works.
    [DataMember]
    public Panel Panel { get; set; }
    //This works, too.
    [DataMember]
    public TwoColumnPanel TwoColumnPanel { get; set; }
    //For this one, however, I only get the one Panel when I deserialize.
    //Why doesn't it properly deserialize the TwoColumnPanel specified in the xml above.
    [DataMember]
    public List<Panel> Panels { get; set; }
}
[DataContract]
[Serializable]
public class Panel
{
    [DataMember]
    public int ColumnAttribute { get; set; }
}
[DataContract]
[Serializable]
[XmlRoot("Panel")]
public class TwoColumnPanel : Panel
{
    public TwoColumnPanel()
    {
        ColumnAttribute = 2;
    }
}

2 个答案:

答案 0 :(得分:3)

[DataContract]
[Serializable]
public class Page
{
    //This works.
    [DataMember]
    public Panel Panel { get; set; }
    //This works, too.
    [DataMember]
    public TwoColumnPanel TwoColumnPanel { get; set; }
    //For this one, however, I only get the one Panel when I deserialize.
    //Why doesn't it properly deserialize the TwoColumnPanel specified in the xml above.
    [DataMember]
    [XmlArray("Panels")]
    [XmlArrayItem("TwoColumnPanel", typeof(TwoColumnPanel))]
    [XmlArrayItem("Panel", typeof(Panel))]
    public List<Panel> Panels { get; set; }
}

答案 1 :(得分:2)

尝试使用XmlArrayItem属性:

[DataMember]
[XmlArrayItem("Panel", typeof(Panel))]
[XmlArrayItem("TwoColumnPanel", typeof(TwoColumnPanel))]
public List<Panel> Panels { get; set; }