0

我创建了一个可以托管插件的简单应用程序。
如果插件提供依赖服务,一切都可以,没有问题,但是当涉及到创建一个操纵主机本身的插件时(例如更改它BackColor,向它添加文本TextBox等),我似乎无法找到解决方案!
由于看起来像循环依赖,我尝试的每种方法都不起作用。
首先,我尝试在我的主机应用程序中创建一些公共SettersGetters内部,当我尝试将它添加为我的引用时,IpluginInterface由于循环依赖你不能说,
我尝试了一个中间类来实现主机应用程序的设置器和获取器,再次我遇到了同样的错误。
我能做些什么来避免这个错误并操纵主机应用程序?

4

1 回答 1

2

创建第三个名为“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");
        }
    }
}
于 2013-04-10T10:01:19.893 回答