【问题标题】:Deserialize runtime created class反序列化运行时创建的类
【发布时间】:2014-11-25 22:52:32
【问题描述】:

我正在尝试使用 C# 和 JSON.net 反序列化运行时创建的类型,但它会引发解析类型异常。

我有一个空的 BaseElement 类,所有运行时创建的类型都从该类继承,所有类型都保证在反序列化过程之前创建,并且我使用 TypeNameHandling = TypeNameHandling.All 设置进行序列化和反序列化。

创建类的过程是这样的(简化为示例):

        AssemblyName asmName = new AssemblyName();
        asmName.Name = "RaspElementTypes";
        AssemblyBuilder asmBuild = Thread.GetDomain().DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);

        ModuleBuilder modBuild = asmBuild.DefineDynamicModule("TypeModule", "RaspElementTypes.dll");   

        TypeBuilder tb = modBuild.DefineType("ClassInfo", TypeAttributes.Class, typeof(BaseElement));

        //Add properties, functions, etc

        Type finalType =  tb.CreateType();
        var item = (finalType)Activator.CreateInstance(tType);

而序列化/反序列化是这样的:

        //Data is a BaseElement[] array with the ClassInfo instances

        //Serialize

        JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
        string res = JsonConvert.SerializeObject(Data, Formatting.Indented, settings);

        //Deserialize

        var deser = JsonConvert.DeserializeObject <BaseElement[]>(res, settings);

确切的错误是这样的:

Newtonsoft.Json.dll 中出现“Newtonsoft.Json.JsonSerializationException”类型的未处理异常 附加信息:错误解析 JSON 'ClassInfo,RaspElementTypes' 中指定的类型。路径'$values[0].$type'。

知道如何反序列化运行时创建的类型吗?

谢谢。

【问题讨论】:

    标签: c# json.net deserialization


    【解决方案1】:

    嗯,找到了,只需要创建一个 SerializationBinder 来提供正确的类型。

    在确切的情况下,活页夹看起来像这样:

    class binder : SerializationBinder
    {
        Type[] types;
        public binder(Type[] Types)
        {
            types = Types;
        }
    
        public override Type BindToType(string assemblyName, string typeName)
        {
            if(assemblyName == "RaspElements")
            {
    
                var type = types.Where(t => t.Name == typeName).FirstOrDefault();
    
                if (type != null)
                    return type;
    
            }
            return Type.GetType(typeName + ", " + assemblyName);
        }
    }
    

    而反序列化的过程改成这样:

    //runtimeTypes is a Type[] with all the runtime generated types, data is the serialized string
    
    JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, Binder = new binder( runtimeTypes ) };
    
    var deser = JsonConvert.DeserializeObject <BaseElement[]>(data, settings);
    

    希望它能帮助遇到我同样情况的人。

    干杯

    【讨论】:

    • 感谢您花时间发布您的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    相关资源
    最近更新 更多