我需要能够反序列化属于运行时加载的不同程序集的对象。加载程序集代码:
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;
}
我还应该提到这是牛顿软件的例外:
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来重新定向程序集绑定似乎无法在运行时加载程序集的这种情况下工作。当它们被反射时,它们仍然作为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>
答案 0 :(得分:0)
我使用这篇文章找到了部分解决方案:
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);
}
}