C# 在反序列化时,Newtonsoft.Json FormatterAssemblyStyle=Simple仍然需要程序集名称中的版本

C# 在反序列化时,Newtonsoft.Json FormatterAssemblyStyle=Simple仍然需要程序集名称中的版本,c#,.net,json.net,deserialization,.net-assembly,C#,.net,Json.net,Deserialization,.net Assembly,我需要能够反序列化作为运行时加载的不同程序集的一部分的对象。加载程序集代码: foreach (string asmPath in Directory.GetFiles(PLUGIN_DIRECTORY, "*.dll")) { var AsmName = AssemblyName.GetAssemblyName(asmPath); var Asm = Assembly.Load(AsmName); _LoadedAssemblies.Add(Asm); } 程序集加载

我需要能够反序列化作为运行时加载的不同程序集的一部分的对象。加载程序集代码:

foreach (string asmPath in Directory.GetFiles(PLUGIN_DIRECTORY, "*.dll"))
{
    var AsmName = AssemblyName.GetAssemblyName(asmPath);
    var Asm = Assembly.Load(AsmName);
    _LoadedAssemblies.Add(Asm);
}
程序集加载得很好,当反序列化整个程序集名为的对象时

"$type": "Plugin.MyRules.Rule1, SmartPlugin, Version=1.0.3.0, Culture=neutral, PublicKeyToken=null"
一切都很顺利。我现在需要做的是能够在运行时加载程序集的任何版本,而无需提供版本信息。我认为使用FormatterAssemblyStyle.Simple设置可以通过使用简单的

"$type": "Plugin.MyRules.Rule1, SmartPlugin"
但事实并非如此。它显然找不到我加载的程序集名称。在这方面我将感谢任何帮助

这是我正在使用的反序列化程序代码:

public static T DeserializeJsonObject<T>(string p_JSONPath)
{
    T returnVal = default(T);
    using (StreamReader reader = new StreamReader(new FileStream(p_JSONPath, FileMode.Open)))
    {
        returnVal = JsonConvert.DeserializeObject<T>(reader.ReadToEnd(), new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple });
    }

    return returnVal;
}
这是堆栈跟踪:

at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolveTypeName(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, String qualifiedTypeName)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadMetadataProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at JSONSerializer.DeserializeJsonObject[T](String p_JSONPath) in c:\EXAMPLE.cs:line 15
在运行时加载程序集的这种情况下,通过添加到app.config来重新定向程序集绑定似乎也不起作用。当它们被反射时,仍然作为dll本身的程序集版本加载

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="SmartPlugin" publicKeyToken="null" culture="en-us" />
      <!-- Assembly versions can be redirected in app, publisher policy, or machine configuration files. -->
      <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="1.0.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

我通过这篇文章找到了部分解决方案:

我没有像那个用户那样使用迁移,而是浏览了已加载程序集的列表,并比较了程序集名称而不是全名。然后,如果匹配,则返回用于生成类型的程序集的全名。我还将CustomNamespaceSerializationBinder添加到JsonSerializerSettings中的Binder属性中

public class CustomNamespaceSerializationBinder : DefaultSerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        foreach (Assembly asm in PluginLoader.GetPluginAssemblies())
        {
            if (asm.FullName.Contains(assemblyName))
            {
                assemblyName = asm.FullName;
                break;
            }
        }

        return base.BindToType(assemblyName, typeName);
    }
}
public class CustomNamespaceSerializationBinder : DefaultSerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        foreach (Assembly asm in PluginLoader.GetPluginAssemblies())
        {
            if (asm.FullName.Contains(assemblyName))
            {
                assemblyName = asm.FullName;
                break;
            }
        }

        return base.BindToType(assemblyName, typeName);
    }
}