snowil
snowil

Reputation: 101

C#. Deserialization into same types depending on attribute

I had been working with deserialization and got stucked.

There is my classes:

public class Parent
{
   public List<Child> child {get;set}
}

public class Child
{
   some properties
}

public class Child1 : Child
{
   some properties
}

public class Child2 : Child
{
   some properties
}

And I have xml:

<Parent>
   <Child AttribName="TypeOne">
   </Child>
   <Child AttribName="TypeTwo">
   </Child>
</Parent>

How can I use some [Xml] attributes to do this? I need List<Child> (Child1 or Child2, depending on attrute AttribName) in Parent

Upvotes: 1

Views: 266

Answers (3)

Alexander Petrov
Alexander Petrov

Reputation: 14231

You can use custom xml reader like this:

public class CustomXmlReader : XmlTextReader
{
    public CustomXmlReader(string url) : base(url) { }

    public override string GetAttribute(string localName, string namespaceURI)
    {
        if (namespaceURI == "http://www.w3.org/2001/XMLSchema-instance" && localName == "type")
        {
            if (base.LocalName == "Child")
            {
                var attr = base.GetAttribute("AttribName");

                if (attr == "TypeOne")
                    return "Child1";
                if (attr == "TypeTwo")
                    return "Child2";
            }
        }
        return base.GetAttribute(localName, namespaceURI);
    }
}

Add attributes to base class:

[XmlInclude(typeof(Child1))]
[XmlInclude(typeof(Child2))]
public class Child

Example usage:

var xs = new XmlSerializer(typeof(Parent));

Parent parent;

using (var xmlReader = new CustomXmlReader("test.xml"))
    parent = (Parent)xs.Deserialize(xmlReader);

Upvotes: 0

snowil
snowil

Reputation: 101

In my case with strong xml format and very big files I have just one solution - custom serialization.

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1062865

XmlSerializer does not support discriminators based on an attribute; only the element name. So you could use XmlSerializer for this - but not your scenario:

<Parent>
   <ChildTypeOne>
   </ChildTypeOne>
   <ChildTypeTwo>
   </ChildTypeTwo>
</Parent>

Options:

  • deserialize it manually
  • transform the xml before deserialization
  • simply change the xml format

Upvotes: 1

Related Questions