gpt4 book ai didi

c# - Newtonsoft.Json FormatterAssemblyStyle=Simple 在反序列化时仍然需要程序集名称中的 Version

转载 作者:太空宇宙 更新时间:2023-11-03 15:32:11 38 4
gpt4 key购买 nike

我需要能够反序列化属于在运行时加载的不同程序集的对象。加载程序集代码:

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;
}

我还应该提到这是 Newtonsoft 异常:

Could not load assembly 'SmartPlugin'.

这是堆栈跟踪:

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 来重定向程序集绑定(bind)似乎也不起作用。它们在反射时仍作为 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>

最佳答案

我使用这篇文章找到了部分解决方案:

https://stackoverflow.com/a/9921190/2996906

我没有像那个用户那样使用迁移,而是浏览了我加载的程序集的列表,并比较了程序集名称而不是全名。然后,如果匹配,则返回组装的全名以构建类型。我还将 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);
}
}

关于c# - Newtonsoft.Json FormatterAssemblyStyle=Simple 在反序列化时仍然需要程序集名称中的 Version,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33420278/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com