2017-04-24 74 views
3

我想用AssemblyResolver事件在我的應用程序中動態加載程序集,但我不明白該怎麼做。運行時程序集解析

我已經看到這個tutorial並自己嘗試過。 在尖端3,他寫道:

static void Main(string[] args) 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; 
} 
static void Print() 
{ 
    var mainClass = new MainClass(); 
    mainClass.Print(); 
} 

static Assembly ResolveAssembly(object sender, ResolveEventArgs args) 
{ 
    return Assembly.LoadFile(@"path to the library"); 
} 

其實我不明白這個代碼應如何編譯在所有... 的new MainClass()不能編譯,因爲它未知的類型(還沒有加載)的加載發生在運行時。
如果MainClass是已知類型,則根本不應解析...

該代碼應如何工作?

+0

我認爲'print'是一些僅用於調試的方法(如調用堆棧),並不意味着加載的程序集中包含的東西。在先前的章節中應該給出這個代碼。 –

回答

0

如果你想加載一個你不知道內容的程序集(然後使用反射來實例化它的類),你可以簡單地使用Assembly.Load(),如果你有它的全名(名字,版本,文化和公鑰令牌如果存在)或Assembly.LoadFrom如果您有它的路徑名。

AssemblyResolve用於「重定向」在編譯時「已知」但在運行時必須從特定路徑加載的程序集的加載。你可以明確地使用它來「誘餌和切換」程序集(在編譯時你有一個程序集,在運行時加載一個實現相同類的不同程序集)。

0

如果編譯因爲那時你有一個參考到圖書館與MainClass型和Print方法,即使是沒有任何實際執行一個空存根 - 或者只是錯誤的執行。它不是「未知的」。如果它是未知的,那麼這個代碼實際上不會編譯,你必須使用反射來在運行時查找類型,反射來實例化實例,反射來調用Print()方法(除非有一些着名的接口或基礎類,你可以投到,或者你使用dynamic)。

這就是你需要編譯的東西:元數據。實際上,它是相對常見的,目標是「參考庫」,這正是您的IDE中多個多目標功能的工作原理。

運行,您可以覆蓋負載提供預期庫,但說實話這是通常更容易只是部署實際庫到應用程序的探測路徑(S)(通常:在主exe文件旁邊)。此外,在您的ResolveAssembly方法中,最好檢查正在請求哪個程序集 - 它可能試圖加載完全不相關的東西,在這種情況下,請將其單獨放置。

+0

但是,如果我將空stub添加爲項目的引用,當出現'New MainClass()'時,將會引發'ResolveAssembly'? – nrofis

+0

@nrofis它會發生在JIT需要它的時候,所以*在最新的時候*當'new MainClass()'運行時,但可能更早 –

+0

即使'MainClass'已知並且存在於引用中? – nrofis