我按照教程如何制作应用程序支持插件。一切似乎都运行良好,但我需要插件才能在主应用程序中调用函数和访问变量,而不仅仅是相反。我有一个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();
}
}
}
答案 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中,以便不会在应用程序域中出现类型不匹配。没有理由不把它放到解决方案中并参考项目。