C#插件:访问母亲形式和功能

时间:2011-10-27 15:03:05

标签: c# plugins interface

我按照教程如何制作应用程序支持插件。一切似乎都运行良好,但我需要插件才能在主应用程序中调用函数和访问变量,而不仅仅是相反。我有一个http包装类,它将监视主应用程序的净使用情况等。该插件将从母应用程序调用http包装器。

我怎样才能做到这一点?我是否需要定义一个包含所有可用函数/变量的类?我还需要插件来生成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?希望有道理,谢谢!

编辑:完整的主应用代码

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();
        }

    }
}

3 个答案:

答案 0 :(得分:0)

您可以采取的一种方法是定义一个接口,其中包含您要从母应用程序调用的所有方法(称为IMother),并让母应用程序实现此功能。

然后您可以更新IPlugin以获得类似void SetMother( IMother mother )的方法,当您加载每个插件时,您可以在插件上调用此方法。这样每个插件从一开始就会有IMother引用,并且可以根据需要调用方法。

关于plugininterface.dll的问题,是的,MainApplication和myPlugin都依赖于那个dll(它不仅仅是开发所需要的)。如果你想避免使用额外的dll(引用额外的dll通常不是问题),我会将插件接口放在与MainApplication相同的项目中。我不确定我是否理解您的布局,所以如果这不能回答您的问题,请添加有关您的项目/解决方案配置方式的更多详细信息。

基于评论的编辑:

我假设你的布局如下:
一个包含三个项目的解决方案文件
MainApplication的一个项目
myPlugin的一个项目
插件界面的一个项目。

您可以将插件界面的代码文件移动到MainApplication项目中。这样MainApplication就不依赖于其他任何东西了。只需从插件接口项目中获取.cs文件并将其添加到MainApplication。然后,您需要从myPlugin引用MainApplication,但这应该没问题。

答案 1 :(得分:0)

与其他任何事情都没有什么不同。为您的插件提供表单的引用。

至于.dll的依赖性,是的..插件和应用程序都是依赖的。但这不是一件坏事。事实上,它非常非常好。我根本不会改变那种架构。

答案 2 :(得分:0)

您必须创建一个新界面,例如IHostPlugin,并通过此界面公开要在插件中使用的主表单的属性。在主表单类中实现接口,或者更好地在可以访问主表单的包装类中实现。将此类设为marshalByref并将其传递给插件,方法是在插件的界面上创建一个方法,该方法将此主机接口作为参数,以便插件具有对主机的引用。

您应该将这些接口保存在单独的dll中,以便不会在应用程序域中出现类型不匹配。没有理由不把它放到解决方案中并参考项目。