我正在尝试使用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'。
关于如何反序列化运行时创建类型的任何想法?
感谢。
答案 0 :(得分:3)
好吧,发现它,只需要创建一个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);
希望它可以帮助处于相同情况的人。
干杯