20

I'm using XMLSerializer to serialize an object that contains a generic list

List <ChildBase> Children {get;set}

The problem is that each element derives from ChildBase which in fact is an abstract class. When I try to deserialize, I get an invalidOperationException

Is there a way I can use XMLSerializer with derived objects? Thanks.

skaffman
  • 398,947
  • 96
  • 818
  • 769
Andrea Nagar
  • 1,233
  • 2
  • 13
  • 23

3 Answers3

49

There are three ways of doing this; either you can use [XmlInclude] against the type, or you can use XmlElement/XmlArrayItem against the property. They are all shown below; uncomment the pair you prefer:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
public class MyWrapper {
    //2: [XmlElement("A", Type = typeof(ChildA))]
    //2: [XmlElement("B", Type = typeof(ChildB))]
    //3: [XmlArrayItem("A", Type = typeof(ChildA))]
    //3: [XmlArrayItem("B", Type = typeof(ChildB))]
    public List<ChildClass> Data { get; set; }
}
//1: [XmlInclude(typeof(ChildA))]
//1: [XmlInclude(typeof(ChildB))]
public abstract class ChildClass {
    public string ChildProp { get; set; }
}
public class ChildA : ChildClass {
    public string AProp { get; set; }
}
public class ChildB : ChildClass {
    public string BProp { get; set; }
}
static class Program {
    static void Main() {
        var ser = new XmlSerializer(typeof(MyWrapper));
        var obj = new MyWrapper {
            Data = new List<ChildClass> {
                new ChildA { ChildProp = "abc", AProp = "def"},
                new ChildB { ChildProp = "ghi", BProp = "jkl"}}
        };
        ser.Serialize(Console.Out, obj);
    }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • And now try to apply this: [XmlRoot(ElementName = "myWrapper", Namespace = "http://URL/")]public class MyWrapper – Brian J. Hakim May 28 '12 at 07:06
  • 1
    Note that method 1 does not seem to work for deserializing a collection. Method 2 or method 3 is needed for the deserializer to figure out how to map the nodes in the xml back to items in the collection. – Craig Jul 06 '16 at 18:46
5

You may use XmlIncludeAttribute for this. Or see this post on another way of doing this.

elder_george
  • 7,849
  • 24
  • 31
0

Another option is to set the types dynamically from derived class if defined in another namespace: XmlAttributeOverride

Kishore A
  • 1,293
  • 3
  • 16
  • 21