2011-10-27 22 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