2017-02-21 41 views
2

我正在開發一個使用插件的程序。所有插件都是從KrotAPI.IKrotAPI接口繼承的類。該接口存儲在krotapi.cs文件中,這對於主機的csproj和每個插件的* .csproj都是通用的。如何從DLL接口訪問類?

使用此代碼

dynamic LoadPlugin(Assembly asm) 
{ 
    foreach (Type type in asm.GetTypes()) 
    { 
    if (type.GetInterface("KrotAPI.IKrotPlugin") != null) 
    { 
     PluginType = type; 
     dynamic inst = Activator.CreateInstance(type); 
     KrotAPI.IKrotPlugin inst2 = inst as KrotAPI.IKrotPlugin; 
     if (inst2 == null) return inst; 
     Console.WriteLine("Link to API is set up."); 
     return inst2; 
    } 
    } 
    throw new Exception("There are no valid plugin(s) in the DLL."); 
} 

inst2主機信息加載插件永遠是空的,我被迫使用慢速和馬車動態調用。如何使它像inst,但與KrotAPI.IKrotPlugin類型?


關於幾乎相同的主題的第二個問題。 一些插件函數返回KrotAPI.FindData類型的結果(這是一個結構,存儲在上面的krotapi.cs文件中)。但我不能訪問它:

dynamic fd = new KrotAPI.FindData(); 
if (NextItemInfo != null) //NextItemInfo is an instance of that struct 
    fd = NextItemInfo; 
listBox1.Items.Add(fd.FileName); 

在最後一排.NET框架拋出此異常:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException 「System.ValueType」不包含定義「文件名」

然而FileName字段在結構硬編碼,肯定不是一個空,或

0123同時結合動態操作

如果我KrotAPI.FindData fd2 = (KrotAPI.FindData) fd; listBox1.Items.Add(fd2.FileName);替換最後一行出現

Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException 一個意外的異常。

WTF?

回答

1

您的主機和插件中已定義了IKrotAPI界面。這意味着它們不是相同的界面。包含的程序集是界面完整標識的一部分。每個插件實際上都實現了一個在自己的程序集中定義的接口,它與主機程序集中定義的接口不同。

有兩種方法來解決這個問題:

  1. 讓你的插件引用主機大會的IKrotAPI接口。
  2. 爲接口和數據類型創建第三個程序集(例如KrotAPI.FindData),它們對於主機和服務器都是通用的。

我個人比較喜歡第二種方法。它允許你升級你的主機程序集而不會使現有的插件失效。爲了對這種裝配使用通用的命名約定,可以將這個第三個裝配稱爲KrotAPI。我傾向於將「API」看作是某人(即插件開發人員)將編碼的接口和數據類型集合,但是對於您的情況,所有實際可運行的代碼都將位於主機或插件中。

+0

謝謝!當我選擇第一種方式時可能會出現什麼麻煩,並且一些插件會比主機exe更舊或更新?目前,我看到它更好,因爲不需要在每個插件的目錄中放置一個KrotAPI.dll文件,並且當插件目錄中沒有Krot.exe時,所有插件仍然可以正常工作(正如我假設的那樣,插件正在使用已經加載到內存中的程序集)。 –

+0

程序集版本號是程序集標識的一部分,該標識隨後成爲界面標識的一部分。這意味着如果更新主機程序集的版本號,則該程序集定義的接口不再是插件程序集使用的接口。這可以通過綁定重定向來緩解。 –

+0

你不需要每個插件目錄中的API程序集。如果你使用的是默認的AppDomain,你可以強制主機應用程序在加載任何插件之前加載API程序集,然後每個插件只使用已經加載的API程序集。你可以用多種方法強制裝配裝配(我通常使用空的靜態方法)。如果你在單獨的AppDomain中隔離你的每個插件,這是一個更多的工作,但你仍然可以讓所有的插件使用一箇中央API程序集。 –