具有从抽象类型扩展的成员的类的XML序列化

时间:2012-04-19 20:14:06

标签: c# .net xml-serialization

尝试运行此代码时遇到InvalidOperationException

示例代码

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

内部异常

  

{“不期望XMLSerializationExample.Car类型。使用XmlInclude或SoapInclude属性指定静态未知的类型。”}

问题

如何修复此代码?还有其他我应该做的事吗?

我在哪里放下以下内容?

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

将属性置于AutoCaravan类之上不起作用。如下例所示,直接将类型添加到XmlSerializer也不起作用。

XmlSerializer xs = new XmlSerializer(typeof(Caravan), new Type[] {
    typeof(Car), typeof(Truck) });

1 个答案:

答案 0 :(得分:2)

我无法解释为什么需要这样做,但除了添加XmlInclude属性之外,您还需要确保您的类指定了一些非null命名空间,因为您已在root(也许是一个bug)。它不一定必须是相同的命名空间,但它必须是某种东西。它甚至可能是一个空字符串,它不能是null(这显然是默认值)。

这序列化很好:

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