如何在RavenDB中使用自定义JSON.NET转换器从动态DLL反序列化为类型?

问题描述:

我的RavenDB对象是根据动态加载的DLL中的类型创建的.我无法将DLL加载到当前AppDomain的执行上下文中,因此JSON反序列化器无法找到类型.

My RavenDB objects are created from types in a DLL that is loaded dynamically. I cannot load the DLL into the execution context of the current AppDomain, so the JSON deserializer can't find the types.

我将如何使用自定义转换器来使用已加载的运行时汇编?

How would I use a Custom Converter to use the types in my loaded-at-runtime Assembly?

NB 我尝试服务通过AppDomain从另一个域下载DLL,但稍后导致冲突.尽管它解决了该问题中的问题,但现在我需要确保所有对象都是根据动态加载的Assembly中的类型创建的.

NB I tried serving the DLL from another domain via the AppDomain but that caused conflicts later. Although it solved the problem in that question, I now need to make sure that all of my objects are created from types in the dynamically loaded Assembly.

在要指定Assembly生成类型的位置,这是创建自定义转换器的方式.我所有的自定义类型均源自IEntity.您需要执行此操作,以便解串器知道何时将钩子插入自定义类.

Where you want to specify the Assembly to generate the types, this is how you create a custom converter. All of my custom types derive from IEntity. You need to do this so that the deserializer knows when hook into your custom class.

public class DynamicAssemblyJsonConverter : JsonConverter
{
    private Assembly dynamicAssembly = null;

    public DynamicAssemblyJsonConverter(Assembly dynamicAssembly)
    {
        this.dynamicAssembly = dynamicAssembly;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);

        var typeName = jObject["$type"].Value<string>().Split(',')[0];

        var target = dynamicAssembly.CreateInstance(typeName);

        serializer.Populate(jObject.CreateReader(), target);

        return target;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType is IEntity;
    }
}

如果您正在使用RavenDB(就像我一样),请创建此CustomConverter,然后将其分配给Conventions.CustomizeJsonSerializer,然后在查询或加载之前将其应用于Raven.

If you are using RavenDB (like I am), create this CustomConverter and then apply it to Raven before you query or load by assigning it to: Conventions.CustomizeJsonSerializer.