C#从插件加载用户控件

时间:2018-11-12 16:35:36

标签: c# plugins runtime appdomain

这是我以前的插件项目HERE

的扩展

我仍处于头脑风暴阶段,但是这个想法很基本。现在,我可以创建一个库,并将其作为插件加载到我的应用程序中,并具有一个向前和向后的消息传递系统,我正在尝试进一步,并在主应用程序的Form中创建一个Tab,从Plugin到管理信息。

一开始,我知道会失败,所以我尝试将UserControl序列化为对象,并将其传递通过插件系统,这将创建一个选项卡,并将该​​控件反序列化为选项卡内容。

即插即用

public interface PluginHost
{
    void AddTabView(string name, object view);
    ...
}

程序调用

public void AddTabView(string name, object view)
{
    if (tabViews.InvokeRequired)
    {
        AddTabViewCallBack d = new AddTabViewCallBack(AddTabView);
        handle.Invoke(d, new object[] { name, view });
    }
    else
    {
        TabPage v = new TabPage();
        v.Text = name;
        tabViews.TabPages.Add(v);
        v.Controls.Add(view as UserControl);
    }
}

此错误的原因是,由于错误System.Runtime.Remoting.RemotingException: 'Remoting cannot find field 'parent' on type 'System.Windows.Forms.Control'.'提示,UserControl无法序列化,更重要的是,它不能传递其父项。

以原始视图为例 enter image description here

我研究中的多个报告建议创建一个脚本系统来从程序上解释控件的构建,而不是尝试传递对象本身。我最好的猜测是创建一个共享的,可序列化的对象,其中包含位置,大小,名称,值以及可以传递回的任何其他相关信息,然后循环遍历以生成所需的UserControl。

[ tl; dr ]

  

如果这是最好的方法,那么就事件而言我有什么选择?   (onclick,selection_changed等)处理以最大程度地减少   插件架构。

我知道我不想对每个场景进行预编程。 ProxyDomain DOES包含一个PerfMethod,它可以允许从插件的字符串名称中调用“方法和函数”,但是我觉得它可能会从Program-> Plugin-> Program-> Plugin中产生大量的来回调用。

PeftMethod (字符串方法名称,对象[]参数,列表框lvErrors)

public object PerfMethod(string methodname, object[] args, ListBox lvErrors)
{
    try
    {
        Type type = null;
        try { type = _assembly.GetType(typeof(FoxBot).Namespace + ".EventHandler"); }
        catch { }
        if (type != null)
        {
            MethodInfo method = type.GetMethod(methodname);

            if (method != null)
            {
                object ret = null;
                execute = new Thread(new ThreadStart(() =>
                {
                    try
                    {
                        object classInstance = Activator.CreateInstance(type, null);
                        if (method.GetParameters().Length > 0)
                        {
                            ret = method.Invoke(classInstance, args);
                        }
                        else
                        {
                            ret = method.Invoke(classInstance, null);
                        }
                    }
                    catch (ThreadInterruptedException)
                    {
                    }
                    catch (Exception e)
                    {
                        //lvErrors.Items.Add("<Scriptor> InvokeException: " + e.ToString() + ".");

                        MessageBox.Show(e.ToString(), "PerfMethod Failure",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                    }
                }));
                execute.Start();
                try
                {
                    while (execute.IsAlive)
                        Application.DoEvents(); //Thread.Sleep(100);
                }
                catch (Exception e)
                {
                    lvErrors.Items.Add("<Scriptor> MethodException: " + e.ToString() + ".");
                }
                return ret;
            }
            else
            {
                lvErrors.Items.Add("<Scriptor> MethodNotFound: " + methodname + ".");
            }
        }
        else
        {
            lvErrors.Items.Add("<Scriptor> TypeNotFound: " + (typeof(FoxBot).Namespace + ".EventHandler") + ".");
        }
        UnloadDomain();
    }
    catch (Exception er)
    {
        lvErrors.Items.Add(er.ToString());
    }
    return null;
}

0 个答案:

没有答案