“Method not found”异常。为什么AppDomain.CurrentDomain.AssemblyResolve不起作用?

5
  1. 有一个应用程序(executor.exe),它使用反射调用类库(lib.dll)中的方法。
  2. executor.exe嵌入了Newtonsoft.Json 8.0版本作为嵌入式资源。
  3. lib.dll引用了Newtonsoft.Json 9.0版本。
  4. lib.dll引用了system.net.http.formatting 4.0.0.21112版本,该版本又引用了Newtonsoft.Json 4.5。
  5. 除了测试之外,我没有机会修改executor.exe.config。

我希望得到什么:

new JsonMediaTypeFormatter().SerializerSettings;

这是从lib.dll中调用的。但它出现了以下错误:

未找到方法:“Newtonsoft.Json.JsonSerializerSettings System.Net.Http.Formatting.JsonMediaTypeFormatter.get_SerializerSettings()”

我试图做什么:

  1. Handling AppDomain.CurrentDomain.AssemblyResolve (subscribed correctly, using ModuleInitializer). But it doesn't rise. After crash have 2 Newtonsoft.Json (with different versions) loaded to AppDomain.
  2. Binding in app config:

     <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed"
     culture="neutral" />
     <bindingRedirect oldVersion="4.0.0.0-5.0.0.0" newVersion="9.0.0.0" />
    

是的,它有效。但我不能使用这个解决方案。在传递后,AppDomain中加载了2个Newtonsoft.Json(具有不同的版本)。

  1. I don't understand why this works (oldVersion="8.0.0.0-9.0.0.0") but:

    <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
    <bindingRedirect oldVersion="8.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
    

异常“方法未找到”不会抛出。在加载了1个Newtonsoft.Json(9.0)到AppDomain之后,但不适合我。

为什么AppDomain.CurrentDomain.AssemblyResolve不能正常工作?我猜问题在于已加载的2个程序集,但我无法更改这种行为。


你说版本8被存储为嵌入式资源。为什么?它如何使用? - Evk
2个回答

7

为什么 AppDomain.CurrentDomain.AssemblyResolve 不起作用?

如果程序集解析失败,事件 AppDomain.CurrentDomain.AssemblyResolve 就会被触发。但这不是你的情况,因为你在应用程序域中已经看到 Newtonsoft.Json 程序集已经被加载。

你捕获 MissingMethodException 是因为 System.Net.Http.Formatting.JsonMediaTypeFormatter.get_SerializerSettings() 返回在 Newtonsoft.Json 4.5 版本中声明的 JsonSerializerSettings。然而,对于无情的 CLR 来说,Newtonsoft.Json 4.5 中的 JsonSerializerSettings 与 Newtonsoft.Json 9.0 中的 JsonSerializerSettings 完全不同。

为了解决这个问题,引入了程序集版本重定向机制(即所提及的 bindingRedirect)。

异常 "方法未找到" 没有抛出。在传递时,已将 1 个 Newtonsoft.Json (9.0) 加载到 AppDomain 中。但对我来说不合适。

实际上,这就是你应该坚持的解决方案。你最好的选择是只加载一个 Newtonsoft.Json 程序集到应用程序域中,并配置版本重定向。

为什么要重新发明轮子并尝试寻找平台提供以外的解决方案呢?如果由于某种奇怪的原因,您被禁止修改应用程序配置,则可以在机器级别上添加程序集重定向。有关详细信息,请参见文章。但是,在.Net中,程序集版本重定向是修复永恒DLL地狱问题的方法。使用任何其他解决方法(即使您设法找到它们)都不会对您有好处。

3

如果您无法应用绑定重定向,您也可以在应用程序启动时使用Assembly.LoadFrom方法加载正确的程序集。在主方法中查找Newtonsoft.Json dlls并加载一个具有所需版本的dll。这样可以避免加载错误版本的程序集。如果您需要代码片段,请告诉我。


似乎这并不能解决 OP 的问题。从问题描述来看,所需的程序集已经加载到应用程序域中,先加载 4.5 版本并不能解决 MissingMethodException 的问题。 - CodeFuller
@CodeFuller,我认为先加载v4.5将防止加载v9.0并解决问题。这基本上就是绑定重定向所做的。但它可能会引起其他问题,很难预测。从我对OP的绑定重定向工作的理解来看,他应该使用我的建议方法加载v9.0,而不是v4.5。并且在v4.5加载到域中之前尽早执行,即尽可能早地执行。 - Andrii Litvinov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接