2011-10-27 46 views
0

我遵循教程如何使應用程序支持插件。一切似乎都工作正常,但我需要插件能夠在主應用程序中調用函數和訪問變量,而不僅僅是其他方式。我有一個http包裝類,將監測淨使用情況等..主應用程序。該插件會從母應用程序調用http wrapper。C#插件:訪問母表的形式和功能

我該如何做到這一點?我是否需要定義一個包含所有可用函數/變量的類?我還需要該插件來生成GUI,以便用戶可以爲其設置一些設置。

這是我走到這一步:

主要用途:

namespace MainApplication 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     List<iPlugin> PLUGIN_LIST = new List<iPlugin>(); 

     public void LoadPlugins() 
     { 
      // load plugins.. 
     } 

     // how do I call this function from a plugin?! 
     public void HTTP() 
     { 
      // do some networking stuff.. 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      LoadPlugins(); 
     } 


    } 
} 

插件接口:

namespace PluginInterface 
{ 
    public interface iPlugin 
    { 
     string GetPluginName(); 

     void callHTTP(); 

     void SerVar(string var); 
    } 
} 

插件:

namespace MyPlugin 
{ 
    public class Main : iPlugin 
    { 
     string variable = ""; 

     public string GetPluginName() 
     { 
      return "MyPlugin"; 
     } 

     public void callHTTP(){ 
      MainApplication.HTTP(); // call HTTP in main application 
     } 

     public void SerVar(string var) 
     { 
      variable = var; 
     } 
    } 
} 

另外,當我按照教程,插件接口是一個單獨的項目,我不得不'添加作爲參考'在MainApplication和myPlugin。這是否意味着我的應用程序和插件依賴於pluginInterface.dll?還是隻是開發需要?如果它們依賴於運行時,我怎樣才能在我的應用程序和插件中定義它,以便我不必使用額外的dll?希望有道理,謝謝!

編輯:全MainApplication代碼

public interface iPlugin 
{ 
    string GetPluginName(); 

    string GetInformation(); 

    void SerVar(string var); 
} 


namespace MainApplication 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     List<iPlugin> PLUGIN_LIST = new List<iPlugin>(); 

     public void LoadPlugins() 
     { 

      string path = Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName; 
      string pluginDir = Path.GetDirectoryName(path) + "\\Plugins"; 

      foreach (string s in Directory.GetFiles(pluginDir, "*.dll")) 
      { 
       // THIS LINE GIVES THE ERROR 
       Type[] pluginTypes = Assembly.LoadFile(s).GetTypes(); 

       foreach (Type t in pluginTypes) 
       { 
        if (t.ToString().Contains("Main")) 
        { 
         iPlugin plugin = Activator.CreateInstance(t) as iPlugin; 

         PLUGIN_LIST.Add(plugin); 
         break; 
        } 
       } 
      } 

     } 



     private void Form1_Load(object sender, EventArgs e) 
     { 
      LoadPlugins(); 
     } 

    } 
} 

回答

0

一種方法,你可以採取的定義包含所有你想從母親的應用程序(稱爲說IMother)調用該方法的接口,以及使母應用程序執行此。

然後,你可以更新IPlugin有一個方法,如void SetMother(IMother mother),當你加載每個插件,你可以在插件上調用此方法。這樣每個插件從一開始就會有參考,並且可以根據需要調用方法。

關於你對plugininterface.dll的問題,是的,MainApplication和myPlugin都依賴於那個DLL(它不僅僅是開發所需要的)。如果你想避免使用額外的DLL(引用額外的DLL通常不是問題),我會把插件接口放在與MainApplication相同的項目中。我不確定我是否理解你的佈局,所以如果沒有回答你的問題,請添加更多關於你的項目/解決方案配置的細節。

編輯基於評論:

我假設你的佈局是類似如下:
一個解決方案文件,其中包含三個項目
爲MainApplication
一個項目 一個項目爲myplugin
一個項目的插件界面。

您可以將插件接口的代碼文件移動到MainApplication項目中。這種方式MainApplication不會依賴於其他任何東西。只需從插件接口項目獲取.cs文件並將其添加到MainApplication。然後您需要從myPlugin引用MainApplication,但那應該沒問題。

+0

主應用程序項目中的插件接口會讓我覺得更有意義。 –

+0

感謝csm!我只想盡可能少地使用dll,因爲應用程序本身將會是單個exe。當用戶下載它時,應用程序將下載所有插件並將其保存在目錄中。如果主應用程序依賴於pluginInterface.dll,那麼它不會工作,我將需要使用另一個不依賴任何東西來完成所有工作的應用程序,我不想這樣做。你能告訴我如何使用我提供的代碼在主應用程序和插件中定義pluginInterface?謝謝! – user1015551

+0

非常感謝,我現在就試試吧! – user1015551

0

這與其他任何東西都沒有什麼不同。給你的插件參考表格。

至於.dll的依賴性,是的,插件和應用程序都是依賴的。但這不是一件壞事。其實它非常非常好。我根本不會改變那點建築。

0

你將不得不創建一個新的接口,比如IHostPlugin,並通過這個接口公開你想要在你的插件中使用的主窗體的屬性。在可以訪問主窗體的包裝類中實現主窗體類或更好的接口。通過在插件的接口上創建一個方法,將此類marshalByref作爲參數傳遞給您的插件,以便您的插件具有對主機的引用。

您應該將這些接口保存在單獨的dll中,這樣您就不會在應用程序域中出現類型不匹配。沒有理由不把它放入解決方案並參考項目。

+0

謝謝!是否有可能將DLL編譯成exe文件? – user1015551

+0

不是一個好主意。您希望您的接口由您在每個AppDomain中加載的所有程序集共享,否則在嘗試實例化它們時會遇到類型不匹配。只需添加一個對dll的引用。 – Kell