2011-11-19 59 views
0

在我的情況下有三個組件:Consumer類,IExposedIface接口和Exposed類實現IExposedIfaceConsumerExposed都與IExposedIface靜態鏈接,但Consumer沒有編譯時參考Exposed動態加載程序集:爲什麼此代碼有效?

我想拿出一個方案,該方案將允許Consumer在運行時加載不同版本的Exposed(取決於輸入數據 - 假設每個輸入文件攜帶其中Exposed版本應該被用來處理它的信息) 。爲了實現這一點,我開始研究AppDomains,現在我有一個基本版本的工作。

到目前爲止,在提供IExposedIface組件到Exposed組件時,有兩種選擇。

  1. 只在ConsumerIExposedIface.dll目錄和處理AppDomain.AssemblyResolve事件爲AppDomain中,我創建的Exposed

  2. ConsumerIExposedIface.dll兩個實例的目錄以及每個Exposed.dll

現在考慮的是我建立Exposed反對這種IExposedIface

public interface IExposedIface 
{ 
    string SaySomething();  
} 

和我建立Consumer反對這種IExposedIface

public interface IExposedIface 
{ 
    string SaySomething(); 
    string SaySomethingDifferent(); 
} 

在第一種情況下,異常

例外:方法'SaySomethingDifferent'類型'Exposed.Exposed'從 程序集'Exposed,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'沒有執行

在那一刻我打電話appDomain.CreateInstanceAndUnwrap(...)在新創建的AppDomain 創建Exposed實例拋出。

這對我來說很合理。

但在第二種情況下,appDomain.CreateInstanceAndUnwrap(...)經過得很好,我可以沒有問題調用檢索對象上的'SaySomething()'方法。例外

的方法 'SaySomethingDifferent' 沒有在接口/類型發現 'IExposedIface.IExposedIface,IExposedIface,版本= 2.0.0.0,文化=中性公鑰=空'。

只有當我實際撥打電話號碼爲SaySomethingDifferent()Consumer

我很驚訝,在這第二種情況下,CLR讓我走了這麼遠......有人可以解釋爲什麼這是可能的嗎?

回答

0
  1. 案例#1意味着Exposed.dll是對錯誤的版本IExposedIface.dll的結合 - 元數據加載器能加載組件時,因爲它發現一個未實現接口的方法來檢測這一點。

  2. 案例#2(可能)意味着除了每個Exposed.dll之外,您還有每個IExposedIface.dll的正確版本,因此每個程序集都可以在其自己的AppDomain中加載。然而,AppDomain A的接口與AppDomain B的接口不同,當調用實際穿過AppDomain邊界時,這只是一個問題。

我建議不要嘗試那些二進制兼容遊戲和寧做正確的版本(即創建一個新的方法新的接口,從舊的接口繼承,所以IExposedIface.dll的新版本是真正向後兼容)。還有其他的是真的很難調試,因爲如果你可以意外地加載版本的IExposedIface.dll,如果它們可以到達窗口,然後你有兩個版本的AppDomain類型導致沒有結束的麻煩;)