I run into an InvalidOperationException
when attempting to run this code.
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;
}
}
{"The type XMLSerializationExample.Car was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}
How do I fix this code? Is there something else that I should be doing?
Where do I put the following?
[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Truck))]
Putting the attributes above the Auto
or the Caravan
classes do not work. Adding the types directly to the XmlSerializer
like the example below does not work, either.
XmlSerializer xs = new XmlSerializer(typeof(Caravan), new Type[] {
typeof(Car), typeof(Truck) });
I can't really explain why this is needed but in addition to adding the XmlInclude
attributes, you'll need to make sure that your classes specify some non-null namespace since you have specified a namespace on the root (a bug perhaps). It doesn't necessarily have to be the same namespace but it has to be something. It could even be an empty string, it just can't be null
(which is the default value apparently).
This serializes fine:
[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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.