Serializing an XML class that has a member extended from an abstract type

I am InvalidOperationException when I try to run this code.

Code example

 using System; using System.Collections.Generic; using System.IO; using System.Xml.Serialization; namespace XMLSerializationExample { class Program { static void Main(string[] args) { Caravan c = new Caravan(); c.WriteXML(); } } [XmlRoot("caravan", Namespace="urn:caravan")] public class Caravan { [XmlElement("vehicle")] public Auto Vehicle; public Caravan() { Vehicle = new Car { Make = "Suzuki", Model = "Swift", Doors = 3 }; } public void WriteXML() { XmlSerializer xs = new XmlSerializer(typeof(Caravan)); using (TextWriter tw = new StreamWriter(@"C:\caravan.xml")) { xs.Serialize(tw, this); } } } public abstract class Auto { public string Make; public string Model; } public class Car : Auto { public int Doors; } public class Truck : Auto { public int BedLength; } } 

Internal exception

{"The XMLSerializationExample.Car type was not expected. Use the XmlInclude or SoapInclude attribute to indicate types that are not known statically." }

Question

How do I fix this code? Is there anything else I should do?

Where can I put the following?

 [XmlInclude(typeof(Car))] [XmlInclude(typeof(Truck))] 

Putting attributes above the Auto or Caravan classes does not work. Adding types directly to the XmlSerializer , as in the example below, also does not work.

 XmlSerializer xs = new XmlSerializer(typeof(Caravan), new Type[] { typeof(Car), typeof(Truck) }); 
0
source share
1 answer

I can’t explain why this is necessary, but in addition to adding the XmlInclude attributes XmlInclude you need to make sure that your classes specify some non-zero namespace, since you specified the namespace in the root directory (there may be an error). This does not have to be the same namespace, but it has to be something. It may even be an empty string, it simply cannot be null (the default is the default).

This serializes perfectly:

 [XmlRoot("caravan", Namespace="urn:caravan")] public class Caravan { [XmlElement("vehicle")] public Auto Vehicle; //... } [XmlInclude(typeof(Car))] [XmlInclude(typeof(Truck))] [XmlRoot("auto", Namespace="")] // this makes it work public abstract class Auto { [XmlElement("make")] // not absolutely necessary but for consistency public string Make; [XmlElement("model")] public string Model; } 
+2
source

All Articles