2012-01-02 65 views
3

我有一个引用第三方库的项目。图书馆的制造商定期发布新版本。我的最终目标是能够在运行时选择在执行期间必须使用哪个版本。在运行时交换强烈签名的程序集

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

“找到的程序集清单定义不匹配的程序集引用”

我是不是supprised看到这个错误,因为大会强烈签名。我寻找方法绕过这一点,但迄今没有任何运气。

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

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

http://msdn.microsoft.com/en-us/library/eftw1fys.aspx

我也看了看动态调用,但后来我失去的类型安全(我的代码广泛使用在届党集中定义的类型)。 - >删除参考很困难。

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

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

注: 逻辑来加载和卸载在运行时已经存在的组件。 没有可用于第三方库的接口

+2

Brr,这是要求DLL地狱作为一项功能。它与强命名没有任何关系,因为[AssemblyVersion]中的不匹配而引发异常。 bindingRedirect确实是唯一很好的解决方案。除非您能说服供应商只增加兼容程序集的[AssemblyFileVersion],否则您会被卡住。否则增加[AssemblyVersion]意味着“不兼容,甚至不尝试”。 – 2012-01-02 15:52:26

+0

@HansPassant AssemblyVersion确实是递增的,导致清单不匹配。说明明显不匹配只能出现在强签名的程序集中才正确吗?还是这个问题也适用于未签名的程序集? [程序集版本控制](http://msdn.microsoft.com/zh-cn/library/51ket42z.aspx) – Nickolas 2012-01-02 19:15:44

+0

不,只有[AssemblyVersion]在这里很重要。它将以完全相同的方式在未签名的程序集上失败。 – 2012-01-02 19:20:32

回答

1

通过处理AppDomain上的AssemblyResolve事件,您可以“解决”此问题(解决方法可能是更好的描述)。处理这个事件给你的代码提供了一个机会,当所有找到程序集的普通方法找不到匹配的版本时,提供需要加载的程序集。

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

一旦确定了正确的加载请求,只需加载程序集的正确版本(Assembly.LoadFrom,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框架使用的程序集的正常版本和强名称检查。这是你在没有其他选择时做的事情,因为(如问题中)供应商已经搞乱了他们的程序集版本。您还依赖于它们不会在引用版本和加载版本之间的程序集中定义的类中发生重大更改 - 即您使用的所有类,属性,方法等仍然存在并具有相同的签名。

至少要维持安全的借口,这将是一个非常好的主意,在AssemblyResolve事件处理程序至少检查:

  1. 加载的程序集的版本比版本要求
  2. 新已加载和请求程序集的公钥标记匹配
相关问题