我创建了一个可以托管插件的简单应用程序
如果插件提供依赖服务,那就没问题,但是当涉及到创建一个操纵主机本身的插件时(例如更改其BackColor
,向其TextBox
添加文本等)我似乎无法找到解决方案!
因为我尝试的每一种方法都不会起作用,因为它似乎是循环依赖
首先,我尝试在我的主机应用程序中创建一些公共Setters
和Getters
,当我尝试将其添加为我IpluginInterface
的引用时,它表示由于您不能循环依赖,
我尝试了一个中产阶级来实现主机应用程序的setter和getter,我再次面临同样的错误
我该怎么做才能避免此错误并操纵主机应用程序?
答案 0 :(得分:2)
创建一个名为“Interfaces”的第三个项目,然后将接口放在那里的主应用程序中。当您插入插件时,通过该接口传入对主应用程序的引用。这可以防止循环引用。
主项目和插件都可以引用“接口”项目。
编辑:这是一个完整的代码示例。现在,当然,为了简单起见,我已将所有内容放在一个文件中,但我添加了关于每个部分通常驻留位置的注释。您提到的参数是插件不知道的类型。在这种情况下,只需在interfaces项目中添加一个新接口,并使该参数从该接口派生。
要运行此操作,请创建一个winforms项目并将该批次粘贴到新类中。然后删除旧表单和Program.cs文件。
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
// This is the program start. Probably the place that would have loaded the plug ins.
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
//Form goes in project one and has a reference to Interfaces.
public class MainForm : Form, IMainForm
{
private TextBox _textBox;
private IPlugIn _thePlugIn;
private Button _aButton;
public MainForm()
{
InitializeComponent();
_thePlugIn = ObtainPlugInsThroughMagic();
}
private IPlugIn ObtainPlugInsThroughMagic()
{
// So this would usually go off and load some DLLs and then instantiate the IPlugIn objects
// We're cheating.
var plugin = new MyPlugIn();
plugin.Initialise(this);
return plugin;
}
public void SetTextBoxValueFromPlugIn(string newText)
{
_textBox.Text = newText;
}
private void InitializeComponent()
{
_textBox = new TextBox();
_aButton = new Button();
SuspendLayout();
_aButton.Location = new Point(20, 50);
_aButton.Size = new Size(100, 25);
_aButton.TabIndex = 1;
_aButton.Click += AButtonClick;
_aButton.Text = "Fire plug in";
_textBox.Location = new Point(20, 10);
_textBox.Size = new Size(260, 20);
_textBox.TabIndex = 0;
AutoScaleDimensions = new SizeF(6F, 13F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(300, 100);
Controls.Add(_textBox);
Controls.Add(_aButton);
Text = "Main form";
ResumeLayout(false);
PerformLayout();
}
private void AButtonClick(object sender, System.EventArgs e)
{
_thePlugIn.MakePlugInDoItsStuff();
}
}
#region interfaces go in the new Interfaces project.
public interface IMainForm
{
void SetTextBoxValueFromPlugIn(string newText);
}
public interface IPlugIn
{
void Initialise(IMainForm mainForm);
void MakePlugInDoItsStuff();
}
#endregion
// The plug in goes in the plug in project and has a reference to Interfaces.
public class MyPlugIn : IPlugIn
{
public IMainForm MainForm { get; private set; }
public void Initialise(IMainForm mainForm)
{
MainForm = mainForm;
}
public void MakePlugInDoItsStuff()
{
MainForm.SetTextBoxValueFromPlugIn("Text set from plug in");
}
}
}