2

所以我有一些用户收到此错误

System.MissingMethodException: Method not found: 'Void System.Net.Http.Headers.HttpHeaders.AddWithoutValidation(System.String, System.Collections.Generic.IEnumerable`1<System.String>)'.
   at System.Net.Http.HttpHeaderExtensions.CopyTo(HttpContentHeaders fromHeaders, HttpContentHeaders toHeaders)
   at System.Net.Http.ObjectContent..ctor(Type type, HttpContent content)
   at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content)
   at Octgn.Site.Api.ApiClient.Login(String username, String password)

我无法在本地重现此问题,但某些使用我的 WPF 应用程序的人最终会遇到此错误。经过一些挖掘日志后,我看到了这个

LOADED ASSEMBLY: System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Net.Http\v4.0_2.0.0.0__b03f5f7f11d50a3a\System.Net.Http.dll

我试过在 csproj 中改变这个

<Reference Include="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
  <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
</Reference>

对此

<Reference Include="System.Net.Http">
  <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
</Reference>

我也尝试将其添加到 app.config 文件中

    <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="1.0.0.0 - 4.0.0.0" newVersion="2.0.0.0"/>
    </dependentAssembly>

这些东西似乎都不想加载与我的项目的 exe 位于同一目录中的 dll。我在本地有 dll,但似乎无法避免 GAC。这是一个产品,所以每天都有数百人使用,所以我希望找到一些不需要用户最终在他们的机器上手动做某事的解决方案。

我也考虑过在加载代码Assembly.Load或类似的代码中抢先加载 dll,但我不确定这是否会产生影响,我认为会有一个更优雅的解决方案。

好的,那么如果我使用ilmerge http://www.microsoft.com/en-us/download/details.aspx?id=17630将所有这些新程序集合并到一个新程序集中呢?或者 GAC 是否使用命名空间等?好吧,我正在尝试...当我让有问题的人对其进行测试时,我会报告它是否有效。

有任何想法吗?

4

4 回答 4

2

如果您正在引用一个强命名的程序集并且该程序集在 GAC 中(具有相同的强名称,即版本号和公钥令牌),那么 .Net 框架将始终从 GAC 加载该程序集,除非该程序集具有已经加载。

如果您有要加载的该 DLL 的副本,则该 DLL需要具有不同的强名称(或不是强名称),以便 .Net 框架可以判断 GAC 中的那个是不同的并且它应该看看其他地方(例如在您的应用程序旁边) - 从事物的声音来看,这将涉及以某种方式修改该 DLL 的本地副本,例如删除强名称

一旦两个 dll 具有不同的强名称(或本地名称不是强名称),使用绑定重定向应该可以正常工作。

更新:或者,您可以尝试在 .Net 框架加载该程序集之前显式加载该程序集的本地副本(例如使用Assembly.Load),在这种情况下,.Net 框架可能会使用已加载的一个而不是查看 GAC。(未经测试)

于 2013-07-03T16:45:13.347 回答
1

我使用了 il​​merge,并将程序集合并到我的库中并绕过它。

于 2013-07-05T07:10:43.790 回答
1

仅供参考,我在我的机器中找不到 System.Net.Http.Headers.HttpHeaders.AddWithoutValidation(...) 方法。但是,我确实看到了 System.Net.Http.Headers.HttpHeaders.TryAddWithoutValidation(...)。

对我来说,您似乎拥有带有旧方法签名的非 RTM 版本的 DLL (System.Net.Http.dll)。由于大多数用户没有安装这个,.NET 将使用本地副本,一切都很好。

有问题的用户可能已经安装了 RTM 版本(可能与不同的软件包捆绑在一起)。在这种情况下,.NET 将使用 GAC 版本,因为它较新。

我支持我在评论中的建议,清理你的开发并从非 RTM 库构建机器,重新编译和重新部署。

于 2013-07-03T16:32:23.373 回答
1

如果 CLR 确定 GAC 中存在足够好的匹配,则无法避免从 GAC (*) 加载程序集。没有多少本地副本对您有帮助。

(*) 你可以尝试甚至不能LoadFrom使用字节:Understanding The CLR Binder

对于加载到 LoadFrom 上下文中的程序集,Binder 首先检查加载上下文中是否已经存在确切的程序集(相同的标识和位置)。如果是,则丢弃 LoadFrom 上下文中的程序集信息,并使用 Load 上下文中的程序集信息。

通过搜索Suzanne Cook 的博客和相关参考资料,可以找到有关程序集加载的更多信息。

注意:在这种特殊情况下,解决方案可能会在 GAC 中检测到这个流氓非 RTM 二进制文件(即通过尝试进行准确的调用并检查“缺少方法”异常)并显示带有解决步骤的消息,而不是试图规避正常加载策略。

于 2013-07-03T02:30:28.360 回答