Как сериализовать производные классы в XML? - PullRequest
2 голосов
/ 23 марта 2012

Представьте себе, что это мой сценарий:

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 ]

12 голосов
/ 23 марта 2012

Вы должны сообщить сериализатору о производных типах

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

Это одно из исключений .Net, которые действительно полезны.Если вы посмотрите на InnerException, вы увидите

Тип FooA не ожидался.Используйте атрибут XmlInclude или SoapInclude, чтобы указать типы, которые не известны статически.

ОБНОВЛЕНИЕ

Основываясь на вашем комментарии о многих производных типах в различных модулях,также может указывать производные типы во время выполнения при создании сериализатора, а не во время компиляции:

Как динамически добавлять атрибут XmlInclude

0 голосов
/ 07 января 2015

Вот хороший метод многократного использования:

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;

} 
...