Сериализация списка <T>в XML с наследованием - PullRequest
4 голосов
/ 26 мая 2009

Я столкнулся с некоторыми проблемами при попытке сериализации моего объекта в XML. Проблема возникает при попытке сериализации свойства «Профили», которое представляет собой список элементов профиля. Профиль мой собственный тип. Тип профиля в идеале должен быть абстрактным, но это не так, поскольку сериализация XML требует ctor без параметров. Свойство Profiles содержит элементы типа "IncomeProfile", "CostProfile", "InvestmentProfile" и т. Д., Которые все, конечно, наследуются от Profile.

Как я уже читал, сериализация этого не поддерживается изначально, поскольку XmlIncludeAttribute допускает только один унаследованный тип. * Т.е. 1003 *

[XmlInclude(typeof(IncomeProfile))]
public List<Profile> Profiles { get; set; }

Какова наилучшая практика при решении этой проблемы? Я пробовал разные решения, используя IXmlSerializable и отражение, однако я не могу десериализовать каждый профиль для правильного типа (все они заканчиваются использованием метода ReadXml (XmlReader reader) типа Profile, хотя отладчик Visual Studio говорит тип объекта - «IncomeProfile» или «CostProfile». Это мой текущий код десериализации, который десериализует xml на три объекта Profile вместо двух IncomeProfile и одного CostProfile:

while(reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Profile")
    {
        String type = reader["Type"];
        var project = (Profile)Activator.CreateInstance(Type.GetType(type));
        project.ReadXml(reader);

        reader.Read();
        this.Profiles.Add(p2);
    }

Любые мысли или предложения очень ценятся!

Ответы [ 2 ]

10 голосов
/ 26 мая 2009

Вам разрешено использовать несколько атрибутов включения - хотя они чаще устанавливаются для самого типа:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
[XmlInclude(typeof(IncomeProfile))]
[XmlInclude(typeof(CostProfile))]
[XmlInclude(typeof(InvestmentProfile))]
public class Profile {
    public string Foo { get; set; }
}
public class IncomeProfile : Profile {
    public int Bar { get; set; }
}
public class CostProfile : Profile { }
public class InvestmentProfile : Profile { }
static class Program {
    static void Main() {
        List<Profile> profiles = new List<Profile>();
        profiles.Add(new IncomeProfile { Foo = "abc", Bar = 123 });
        profiles.Add(new CostProfile { Foo = "abc" });
        new XmlSerializer(profiles.GetType()).Serialize(Console.Out, profiles);
    }
}
3 голосов
/ 26 мая 2009

Вам просто нужно использовать несколько атрибутов [XmlInclude]. Это хорошо работает.

...