将继承的List<T>序列化为XML

4
我在尝试将我的对象序列化为XML时遇到了一些问题。当尝试将“Profiles”属性(一个Profile项目列表)序列化时,问题就出现了。Profile是我自己定义的类型。
理想情况下,Profile类型应该是抽象的,但它不是,因为XML序列化需要一个无参数的构造函数。Profiles属性包含各种类型的项目,如"IncomeProfile"、"CostProfile"、"InvestmentProfile"等,这些类型都继承自Profile。
据我所知,由于XmlIncludeAttribute只允许一个继承类型,因此不支持原生的序列化。
[XmlInclude(typeof(IncomeProfile))]
public List<Profile> Profiles { get; set; }

什么是解决这个问题的最佳实践?我已经尝试了使用IXmlSerializable和反射的不同解决方案,但是似乎无法将每个配置文件反序列化为正确的类型(尽管Visual Studio调试器显示对象的类型为"IncomeProfile"或"CostProfile",它们最终都使用Profile类型的ReadXml(XmlReader reader)方法)。以下是我的当前反序列化代码,它将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

您可以使用多个include属性 - 尽管它们更常用于设置类型本身:

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

我在Profiles属性上尝试了以下内容,但不起作用:[XmlInclude(typeof(IncomeProfile)), XmlInclude(typeof(CostProfile))]但是当我现在将它们设置在Profile类上时,它起作用了。我离成功很近,花了很多时间尝试编写自己的序列化方法。有点恼人,但非常感谢 :) - atsjoo
以下两者有什么区别吗? A: [XmlInclude(typeof(IncomeProfile)), XmlInclude(typeof(CostProfile))]B: [Xmlinclude(typeof(IncomeProfile))] [Xmlinclude(typeof(CostProfile))] - atsjoo

3
您只需使用多个 [XmlInclude] 属性即可。这样做效果很好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接