【问题标题】:XML deserialization of derived classes派生类的 XML 反序列化
【发布时间】:2014-04-22 07:13:40
【问题描述】:

如何创建可以采用类对象或任何派生类的反序列化方法?

public class Config
{
    public string appname;
}

public class CustomConfig1 : Config
{
    public string CustomConfig1Param1;
    public string CustomConfig1Param2;
}

public class CustomConfig2 : Config
{
    public string CustomConfig2Param1;
    public string CustomConfig2Param2;
}

我想得到类似定义输入对象类型的序列化方法:

public string serialize(object obj)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    StringWriter serialized = new StringWriter();
    serializer.Serialize(serialized, obj);
    return serialized.ToString();
}

但是当我从 DB 中读取 XML 时,我无法定义对象的类型,所以我无法将它传递给 XmlSerializer。它可能是 Config 对象或任何派生类

请帮忙。如何定义输入对象的类型?

【问题讨论】:

  • 小观察:公开公共字段是不好的做法

标签: c# .net serialization


【解决方案1】:
[XmlInclude(typeof(CustomConfig1))]
[XmlInclude(typeof(CustomConfig2))]
public class Config
{
    public string appname;
}

然后只需序列化/反序列化指定typeof(Config);该库将根据数据为您返回适当类型的实例。


编辑:完整示例,包括不硬编码子类型的偏好:

using System;
using System.IO;
using System.Xml.Serialization;

public class Config
{
    public string appname;
}

public class CustomConfig1 : Config
{
    public string CustomConfig1Param1;
    public string CustomConfig1Param2;
}

public class CustomConfig2 : Config
{
    public string CustomConfig2Param1;
    public string CustomConfig2Param2;
}

static class Program
{
    static void Main()
    {
        var original = new CustomConfig1
        {
            appname = "foo",
            CustomConfig1Param1 = "x",
            CustomConfig1Param2 = "y"
        };
        var xml = Serialize(original);
        var clone = DeserializeConfig(xml);
        Console.WriteLine(clone.appname);
        var typed = (CustomConfig1)clone;
        Console.WriteLine(typed.CustomConfig1Param1);
        Console.WriteLine(typed.CustomConfig1Param2);
    }
    public static string Serialize(Config obj)
    {
        using (var serialized = new StringWriter())
        {
            GetConfigSerializer().Serialize(serialized, obj);
            return serialized.ToString();
        }
    }
    public static Config DeserializeConfig(string xml)
    {
        using(var reader = new StringReader(xml))
        {
            return (Config)GetConfigSerializer().Deserialize(reader);
        }
    }
    static Type[] GetKnownTypes()
    {
        // TODO: resolve types properly
        return new[] { typeof(CustomConfig1), typeof(CustomConfig2) };
    }
    private static XmlSerializer configSerializer;
    public static XmlSerializer GetConfigSerializer()
    {
        return configSerializer ?? (configSerializer =
            new XmlSerializer(typeof(Config), GetKnownTypes()));
    }
}

【讨论】:

  • 因此基类必须具备派生类的知识。是否存在基类不知道派生类的解决方案,例如,当它们位于单独的程序集中时?
  • @VictorMukherjee 是的:您可以在运行时在构造函数重载中将包含的子类型列表传递给XmlSerializer但是如果您这样做,您需要非常小心地存储和重用序列化程序实例。它工作得很好。我将在一个示例中进行编辑。
猜你喜欢
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多