C# 在运行时交换强签名程序集

C# 在运行时交换强签名程序集,c#,plugins,dll,assemblies,C#,Plugins,Dll,Assemblies,我有一个项目涉及第三方图书馆。库的制造商定期发布新版本。我的最终目标是能够在运行时选择在执行期间必须使用哪个版本 目前,我正在尝试在运行时加载一个版本号高于编译期间使用的版本号的程序集。我编译我的项目,用新版本替换第三方库,并尝试运行应用程序。这就是我遇到的问题。我得到一个错误,说: “定位的程序集的清单定义与程序集引用不匹配” 我不希望看到这个错误,因为程序集是强签名的。我想办法绕过这个,但到目前为止没有任何运气 我认为绑定重定向可以帮助我,但它的缺点是不能指定一系列“新版本”。任何组合都应该

我有一个项目涉及第三方图书馆。库的制造商定期发布新版本。我的最终目标是能够在运行时选择在执行期间必须使用哪个版本

目前,我正在尝试在运行时加载一个版本号高于编译期间使用的版本号的程序集。我编译我的项目,用新版本替换第三方库,并尝试运行应用程序。这就是我遇到的问题。我得到一个错误,说:

“定位的程序集的清单定义与程序集引用不匹配”

我不希望看到这个错误,因为程序集是强签名的。我想办法绕过这个,但到目前为止没有任何运气

我认为绑定重定向可以帮助我,但它的缺点是不能指定一系列“新版本”。任何组合都应该有效,旧版本与新版本,反之亦然

 <bindingRedirect oldVersion="1.2.7.0" newVersion="1.2.8.0" /> 

我还研究了动态调用,但随后我放松了类型安全性(我的代码广泛使用第三方程序集中定义的类型)。-->删除引用是困难的

删除项目定义引用中的公钥也没有帮助。编译期间使用的任何其他程序集版本都会失败

<Reference Include="<assemblyname>">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\..\Dependencies\<manufacturer>\1.2.7.0\<assemblyname>.dll</HintPath>
</Reference>

假的
..\..\Dependencies\\1.2.7.0\.dll
注: 在运行时加载和卸载程序集的逻辑已存在。 第三方库没有可用的接口

您可以通过在AppDomain上处理事件来“修复”此问题(解决方法可能是更好的描述)。当查找程序集的所有常规方法都无法找到匹配的版本时,处理此事件使代码有机会提供需要加载的程序集

在事件处理程序中,您需要检查ResolveEventArgs.Name属性,以查看程序集是否是您需要加载的程序集。Name属性将是正在加载的程序集的长名称,即“Widget.Net,Version=1.2.3.4,Culture=neutral,PublicKeyToken=xxxxxxxxxx”

一旦确定了正确的加载请求,只需加载程序集的正确版本(,assembly.load,assembly.LoadWithPartialName)并从事件处理程序返回它。请注意,Assembly.LoadWithPartialName标记为已过时,但如果目标程序集位于GAC中,则似乎是处理此问题的唯一方法

// application initialization
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    if (args.Name.StartsWith("Widget.Net, Version="))
    {
        Assembly result = Assembly.LoadFrom("Widget.Net.dll");
        return result;
    }
    return null;
}
重要的是要意识到,虽然这“解决”了问题,但从任何意义上讲,这都不是一个好的解决方案。它完全颠覆了.Net framework使用的程序集的正常版本和强名称检查。当您没有其他选择时,您可以这样做,因为(如问题中所述)供应商将其程序集的版本控制搞砸了。您还依赖于它们在引用版本和加载版本之间对程序集中定义的类所做的无中断更改,即您使用的所有类、属性、方法等仍然存在并具有相同的签名

为了保持至少一种安全性的伪装,最好至少在AssemblyResolve事件处理程序中签入以下内容:

  • 加载的程序集版本比请求的版本新
  • 加载的程序集和请求的程序集的公钥令牌匹配

  • Brr,这是要求DLL地狱作为一个功能。它与强命名无关,由于[AssemblyVersion]中的不匹配而引发异常。bindingRedirect确实是唯一好的解决方案。除非您能说服供应商只增加兼容程序集的[AssemblyFileVersion],否则您将陷入困境。否则递增[AssemblyVersion]意味着“不兼容,甚至不要尝试”。@HansPassant AssemblyVersion确实递增,导致清单不匹配。如果说清单不匹配只能发生在强签名程序集上,是否正确?或者该问题是否也适用于未签名的程序集?不,这里只有[AssemblyVersion]重要。它将以完全相同的方式在未签名的程序集上失败。