为什么在反序列化期间尝试解析派生类型时出现错误? (Newtonsoft.Json)

问题描述 投票:0回答:1

每当序列化数据包含派生类型时,只要尝试从json反序列化类,都会出错。我的最终目标是能够存储各种派生类型,所以这是一个问题。当我在序列化的对象中仅存储非派生类型时,不会发生该错误。对于添加的上下文,该代码是使用Revit的AddinManager扩展运行的加载项的一部分。

(根据建议,我重新编写了代码以尝试找出问题并给出更易于理解的描述。我已将代码更改为使用两个简单的类。)

更改后,我现在收到错误:

在JSON'AddinNamespace.ToyNodePlus,AddinAssemblyName,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'中指定的类型与'AddinNamespace.ToyNode,AddinAssembly,Version = 1.0.0.0,Culture = neutral,PublicKeyToken =空值'。路径“ TestNode。$ type”,第1行,位置61。

AddinSettings

namespace AddinNamespace
{
    public class AddinSettings
    {   
        public const string Filename = "AddinSettings.json";

        public ToyNode TestNode;
    }
}

ToyNode和ToyNodePlus定义

namespace AddinNamespace
{
    public class ToyNode
    {
        public string Name;
    }

    public class ToyNodePlus : ToyNode
    {
        public int AdditionalValue;
    }
}

序列化代码

private JsonSerializerSettings serializerSettings = null;

private void OnAddinStart(){
    serializerSettings = new JsonSerializerSettings() 
    { 
    TypeNameHandling=TypeNameHandling.Auto,
    TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple
    };
    if(File.Exists(AddinSettings.Filename)){
        string fileContents = File.ReadAllText(AddinSettings.Filename);
        AddinSettings settings = JsonConvert.DeserializeObject<AddinSettings> (fileContents, serializerSettings);

        //do work with settings here
    }
}

//code for saving to Json (code appears to be working as expected)
private void OnAddinFinish(){
    AddinSettings settings = new AddinSettings();
    settings.TestNode = new ToyNodePlus() {AdditionalValue = 7, Name= "This is a test" };
    string fileContents = JsonConvert.SerializeObject(settings, serializerSettings);
    File.WriteAllText(AddinSettings.Filename, fileContents);
}

创建的Json文件内容

{"TestNode":{"$type":"AddinNamespace.ToyNodePlus, AddinAssembly","AdditionalValue":7,"Name":"This is a test"}}
c# json json.net revit-api
1个回答
0
投票

我想我找到了答案。实际上,我不得不查看github上的source code来找到答案,但最终我能够找出错误发生在哪一行。

此特定错误是由触发以下检查的JsonSerializerInternalReader.ResolveTypeName(..)中的检查引发的]

!objectType.IsAssignableFrom(specifiedType)

调查错误最终导致了此stackoverflow post。我的情况下的特定问题是由于我的代码被作为类库调用,并且调用的应用程序在第一次调用后将旧的.dll文件缓存在temp文件夹中而引起的。因为dll在技术上不同Type.IsAssignable(Type)返回了false。

我最终不得不编写一个自定义的SerializationBinder并将其添加到JsonSerializerSettings参数中,以确保使用一致的程序集。 (下面的实现)。我不确定这是否是最好的处理方式,所以如果有人有其他替代解决方案或改进...

class CustomSerializationBinder : ISerializationBinder
{
    private Dictionary<string, Assembly> assemblyLookup = new Dictionary<string, Assembly>();
    private Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
    public CustomSerializationBinder(List<Assembly> problemAssemblies = null)
    {
        if (problemAssemblies == null) problemAssemblies = new List<Assembly>();
        foreach(Assembly assembly in problemAssemblies)
        {
            if(!assemblyLookup.ContainsKey(assembly.GetName().Name))
                this.assemblyLookup.Add(assembly.GetName().Name,assembly);
        }
        foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            if(!assemblyLookup.ContainsKey(assembly.GetName().Name))
                assemblyLookup.Add(assembly.GetName().Name, assembly);
        }
    }

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        assemblyName = serializedType.Assembly.FullName;
        typeName = serializedType.FullName;
    }

    public Type BindToType(string assemblyName, string typeName)
    {
        Type resolvedType;
        Assembly resolvedAssembly;
        typeCache.TryGetValue(typeName, out resolvedType);
        if (resolvedType != null) return resolvedType;

        assemblyLookup.TryGetValue(assemblyName, out resolvedAssembly);
        if (resolvedAssembly == null) return null;
        resolvedType = resolvedAssembly.GetType(typeName);
        if (resolvedType != null)
            typeCache.Add(typeName, resolvedType);
        return resolvedType;
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.