如何在Xml中序列化派生类?

时间:2012-03-22 21:18:15

标签: c# xml serialization xml-serialization

想象一下这就是我的情景:

public abstract class Foo
{
    public abstract int X { get; set; }
}

public class FooA : Foo
{
    public override int X { get; set; }
    public int Y { get; set; }
}

public class FooB : Foo
{
    public override int X { get; set; }
    public int Z { get; set; }
}

这是一个服务,我有一些序列化的对象。

public class FooService
{
    public List<Foo> GetModels()
    {
        return new List<Foo>()
        {
            new FooA() { X = 3, Y = 6 },
            new FooB() { X = 5, Z = 10 }
        };
    }
}

这是我无法序列化对象的方法,它抛出异常。我想序列化派生类。

    private void SerializeObjects()
    {
        FooService service = new FooService();
        var a = service.GetModels();

        XmlSerializer x = new XmlSerializer(a.GetType());
        TextWriter writer = new StreamWriter("A.xml");

        x.Serialize(writer, a);
        writer.Close();
    }

2 个答案:

答案 0 :(得分:12)

您必须告诉序列化器有关派生类型的信息

[XmlInclude(typeof(FooA))]
[XmlInclude(typeof(FooB))]
public abstract class Foo
{
    public abstract int X { get; set; }
}

这是真正有用的.Net异常选择之一。如果你看一下InnerException,你会看到

  

不期望FooA类型。使用XmlInclude或SoapInclude   attribute用于指定静态未知的类型。

<强>更新

根据您对不同模块中许多派生类型的注释,您还可以在创建序列化程序时而不是在编译时指定运行时的派生类型:

How to add XmlInclude attribute dynamically

答案 1 :(得分:0)

这是一个很好的可重用方法:

string sSerialData = "";

SerializeQueueType<BaseClassType>(oDerivedObject, out sSerialData)


private bool SerializeDerivedObject<T>(T oDerivedObject, out string sOutput)
{
    bool bReturn = false;

    sOutput = "";

    try
    {

        Type[] arrTypes = new Type[1];
        arrTypes[0] = oDerivedObject.GetType();

        XmlSerializer xmlSerl = new XmlSerializer(typeof(T), arrTypes); 
        System.IO.MemoryStream memStream = new System.IO.MemoryStream();
        xmlSerl.Serialize(memStream, oDerivedObject); 

        memStream.Position = 0;

        using (var reader = new System.IO.StreamReader(memStream, Encoding.UTF8))
        {
            sOutput = reader.ReadToEnd();
        }

        bReturn = true;

    }
    catch (Exception ex)
    {
        //_log.Error(ex);
    }


    return bReturn;

}