按类型属性继承XML反序列化

时间:2013-06-07 02:58:05

标签: c# xml serialization deserialization

我的XML看起来像这样:

<root>
    <base type="a">
        <common>1</common>
        <concreteA>one</concreteA>
    </base>
    <base type="b">
        <common>2</common>
        <concreteB>two</concreteB>
    </base>
</root>

这样的课程:

public class Root
{
    public List<Base> Bases { get; set; }
}

public class Base
{
    public int Common { get; set; }
}

public class A : Base
{
    public string ConcreteA { get; set; }
}

public class B : Base
{
    public string ConcreteB { get; set; }
}

如何将其反序列化为对象?当每个基本节点使用XmlArrayItemAttribute( ElementName, Type )]使用不同的名称时,我看到很多posts如何执行此操作,但我需要根据元素type属性选择它。

1 个答案:

答案 0 :(得分:0)

这是一种非常基本的方式,但我认为它有效。我认为如果类类型是一个元素而不是一个属性,那么你应该能够以声明方式解析它。

代码基本上打开了type属性top确定要创建的子类,然后手动填充具体属性和公共属性。

[System.Xml.Serialization.XmlType("base")]
public class Base
{
    [System.Xml.Serialization.XmlElement("common")]
    public int Common { get; set; }
}

public class A : Base
{
    public string ConcreteA { get; set; }
}

public class B : Base
{
    public string ConcreteB { get; set; }
}

[System.Xml.Serialization.XmlRootAttribute("root")]
public class Root : System.Xml.Serialization.IXmlSerializable
{
    [System.Xml.Serialization.XmlElement("base")]
    public List<Base> Bases { get; set; }

     public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        this.Bases = new List<Base>();
        var document = XDocument.Load(reader);

        foreach (var element in document.Root.Elements())
        {
            Base baseElement = null;

            var attr = element.Attribute("type");

            if(attr.Value == "a")
            {
                var a = new A();
                a.ConcreteA = element.Element("concreteA").Value;
                baseElement = a;
            }
            else
            {
                var b = new B();
                b.ConcreteB = element.Element("concreteB").Value;
                baseElement = b;
            }

            baseElement.Common = int.Parse(element.Element("common").Value);
            this.Bases.Add(baseElement);
        }

        this.Bases.Dump();
    }

    public void WriteXml(XmlWriter writer)
    {
        throw new NotSupportedException();
    }
}

void Main()
{
    var xmlString = @"<root>
    <base type=""a"">
        <common>1</common>
        <concreteA>one</concreteA>
    </base>
    <base type=""b"">
        <common>2</common>
        <concreteB>two</concreteB>
    </base>
</root>";

    var stream = new StringReader(xmlString);
    var deserializer = new System.Xml.Serialization.XmlSerializer(typeof(Root));
    var result = (Root)deserializer.Deserialize(stream);    
}