2

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

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

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

谢谢你的想法!

4

2 回答 2

3

If you store the Assembly Qualified Name of the new type in the database, you'll be able to use that to instantiate an instance of the type without changing the type loading code. The implementation looks like this:

        string assemblyQualifiedName = getAssemblyQualifiedNameFromDatabase();

        var futureType = Type.GetType(assemblyQualifiedName);

        var serializer = new DataContractJsonSerializer(futureType);

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

Note that there are no case statements: it is not necessary to know the actual type in advance. However, this code assumes that you have included the new type, either directly in the project or by reference. If you want to dynamically load new types using an assembly that hasn't been recompiled with a reference to the new type, then you'll have to load the assembly that contains the new type and use a reference to the loaded assembly in order to create the type reference.

于 2013-07-13T03:08:07.350 回答
2

您提到您不能轻松地从基类型转换为派生类型。这是为什么?我能够这样做。我的 Dog 实体有一个在 Animal 基本类型中不存在的属性 (DogYears),但我仍然可以将 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
}
于 2013-07-13T02:20:28.147 回答