简体   繁体   English

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

[英]Inheritance XML Deserialization by Type Attribute

I have XML that looks something like this: 我有看起来像这样的XML:

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

And classes like this: 和这样的类:

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; }
}

How can I deserialize this into objects? 如何将其反序列化为对象? I've seen many posts on how to do it when each base node has a different name using XmlArrayItemAttribute( ElementName, Type )] , but I need to choose it based on the elements type attribute instead. 当使用XmlArrayItemAttribute( ElementName, Type )]每个基本节点都有不同的名称时,我已经看到很多有关如何执行此操作的文章 ,但是我需要根据elements type属性进行选择。

This is a very basic way of doing it, but I think it works. 这是一种非常基本的方法,但是我认为它是有效的。 I think if the class type was an element instead of an attribute then you should be able to parse it declaratively. 我认为,如果类类型是元素而不是属性,那么您应该可以声明性地解析它。

The code basically switches on the type attribute top determine what subclass to create and then manually populates the concrete properties and the common property. 代码基本上在type属性的顶部打开,确定要创建的子类,然后手动填充具体属性和common属性。

[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);    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM