DeSerialize为未知派生类型

时间:2013-07-12 23:06:37

标签: c# .net serialization deserialization

我将序列化对象存储为数据库中的json(或将来可能是xml)。在稍后的某个时刻,这个物体将被拉动并被动脉化。基类是HighChart,但也有几种派生类型,例如HighChart.ColumnBarChart。图表的类型存储在JSON中。问题是我无法弄清楚我将如何动态选择要反序列化的类。

我的解决方案需要提供一种自动考虑未来派生类型的方法(我将扩展图表类型的数量,并且不希望为每种图表类型编写新的东西)。

我知道我可以将类型存储到单独的DB字段中 - 但是我必须在我的Deserialize方法中为每种类型使用switch语句。我也可以解析json字符串并发现图表类型,但是再次 - 我必须为每种可能的类型使用switch语句。

感谢您的想法!

2 个答案:

答案 0 :(得分:3)

如果将新类型的Assembly Qualified Name存储在数据库中,您将能够使用它来实例化该类型的实例,而无需更改类型加载代码。实现如下:

        string assemblyQualifiedName = getAssemblyQualifiedNameFromDatabase();

        var futureType = Type.GetType(assemblyQualifiedName);

        var serializer = new DataContractJsonSerializer(futureType);

        var result = (HighChart)serializer.ReadObject(stream);

请注意,没有案例陈述:没有必要事先知道实际类型。但是,此代码假定您已直接在项目中或通过引用包含新类型。如果要使用未通过引用新类型重新编译的程序集动态加载新类型,则必须加载包含新类型的程序集并使用对已加载程序集的引用以便创建类型引用。

答案 1 :(得分:2)

您提到您无法轻松地从基类型转换为派生类型。这是为什么?我能够这样做。我的Dog实体有一个属性(DogYears),它在Animal基类型中不存在,但我仍然可以将Dog反序列化为Animal,然后将其转换并显示DogYears。

public class Dog : Animal
{
    public int DogYears { get; set; }  // This doesn't exist in the base class

    public Dog()
    {
        this.DogYears = 4;
    }
}

在这里,我们将Dog序列化为基类型,然后反序列化为基类型,但我们仍然可以显示特定于狗的属性:

private static void JsonSerialization()
{
    Animal dog = new Dog();

    var stream = new MemoryStream();

    var serializer = new DataContractJsonSerializer(typeof(Animal));

    serializer.WriteObject(stream, dog);

    stream.Position = 0;

    Animal deserializedDog = serializer.ReadObject(stream) as Animal;

    Console.WriteLine(((Dog)deserializedDog).DogYears);
}

控制台正确显示“4”。

为了完整性,这里是Animal类:

[KnownType(typeof(Dog))]
public abstract class Animal
{
    // Properties here
}