c#插件:访问母表单和函数

本文关键字:表单 函数 访问 插件 | 更新日期: 2023-09-27 18:12:29

我遵循了如何使应用程序支持插件的教程。一切似乎都工作得很好,但我需要的插件能够调用函数和访问变量在主要应用程序,而不仅仅是其他方式。我有一个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?希望这有意义,谢谢!

编辑:完整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();
        }
    }
}

c#插件:访问母表单和函数

您可以采用的一种方法是定义一个接口,该接口包含您希望从母应用程序(例如称为IMother)调用的所有方法,并使母应用程序实现此接口。

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

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

根据注释编辑:

我假设你的布局是这样的:
一个包含三个项目的解决方案文件
MainApplication的一个项目
myPlugin的一个项目一个插件接口项目。

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

这和别的没什么不同。给你的插件一个表单的引用。

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

你必须创建一个新的接口,比如IHostPlugin,并通过这个接口公开你想在插件中使用的主表单的属性。在主表单类中实现接口,或者最好是在可以访问主表单的包装器类中实现接口。创建这个类marshalByref,并通过在你的插件接口上创建一个方法将它传递给你的插件,这个方法将这个主机接口作为参数,这样你的插件就有了一个对主机的引用。

你应该把这些接口放在一个单独的dll中,这样你就不会有跨应用程序域的类型不匹配。