2012-01-02 22 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. 新已加載和請求程序集的公鑰標記匹配
相關問題