Q: Why do I get errors when trying to resolve a derived type during deserialization? (Newtonsoft.Json) I get errors whenever I try to deserialize classes from json whenever the serialized data contains a derrived type. My end goal is to be able to store a variety of derived types so this is a problem. The error does not occur when I store only non-derived types in object I serialized. For added context the code is part of an add-in being run using Revit's AddinManager extension.
(Upon suggestion, I reworked the code to try and isolate the problem and give a more conveyable description. I have changed the code to use two simple classes instead.)
After the changes I now get the Error: 

Type specified in JSON 'AddinNamespace.ToyNodePlus, AddinAssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not compatible with 'AddinNamespace.ToyNode, AddinAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Path 'TestNode.$type', line 1, position 61.

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

        public ToyNode TestNode;
    }
}

ToyNode and ToyNodePlus definitions
namespace AddinNamespace
{
    public class ToyNode
    {
        public string Name;
    }

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

Serialization Code
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);
}

Created Json File Contents
{"TestNode":{"$type":"AddinNamespace.ToyNodePlus, AddinAssembly","AdditionalValue":7,"Name":"This is a test"}}


A: I think I found the answer. I actually had to look through the source code on github to find the answer, but I eventually was able to find out which line the error occurs on.
This specific error is thrown by a check in JsonSerializerInternalReader.ResolveTypeName(..) when the following check is triggered
!objectType.IsAssignableFrom(specifiedType)

Looking into the error eventually turned up this stackoverflow post.
The specific problem in my case was caused because my code was being called as a class library and the calling application was caching old .dll files in a temp folder after the first call. Because the dlls were technically different Type.IsAssignable(Type) returned false.
I ended up having to write a custom SerializationBinder and adding it to the JsonSerializerSettings parameter in order to make sure that consistent assemblies were used. (Implementation below). I am not sure if this was the best way to handle it, so if anyone has any alternative solutions or improvements...
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;
    }
}


