XML Serialization of Class Which Has a Member Extended From an Abstract Type

对着背影说爱祢 提交于 2019-12-23 06:57:55

问题


I run into an InvalidOperationException when attempting to run this code.

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

Inner Exception

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

Question

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

回答1:


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


来源:https://stackoverflow.com/questions/10236014/xml-serialization-of-class-which-has-a-member-extended-from-an-abstract-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!