宿主插件模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了宿主插件模式相关的知识,希望对你有一定的参考价值。

 

  记得在学校的时候, 老师为了开拓我们的眼界, 给我们上了一堂有关反射的用法,随后给我们现场演示了一个宿主插件的例子. 虽然后来我没有在实际的项目中用到这个知识点,但是我觉得这个是一个不错的东西.

    自己定义一个宿主,然后对外提供接口, 大家按照统一的接口规范来,这样就能大家一起开发,完善该插件.

    我这里先说一下"宿主", 宿主一般作为一个启动器,可以有一些基础的功能,也可以没有, 宿主提供统一的接口, 对外的插件实现该接口, 然后宿主通过加载dll,反编译,调用插件里面的方法,做对应的操作或者显示.

    这里介绍一种 基于Winform的宿主--插件

   

   宿主 是一个Winform页面, 里面一个 TableControl, 每个插件 进来,就显示一个 TabPage,这样各个插件才不会冲突. 

   

技术分享
partial class Form1
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.tbcontr = new System.Windows.Forms.TabControl();
            this.SuspendLayout();
            // 
            // tbcontr
            // 
            this.tbcontr.Location = new System.Drawing.Point(12, 12);
            this.tbcontr.Name = "tbcontr";
            this.tbcontr.SelectedIndex = 0;
            this.tbcontr.Size = new System.Drawing.Size(437, 269);
            this.tbcontr.TabIndex = 0;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(461, 303);
            this.Controls.Add(this.tbcontr);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.TabControl tbcontr;

    }
View Code

 

  

 

   插件接口:  一个控件,一个文本

               

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace plusInterfaces
{
    public interface plusUI
    {
        Control GetUI();

        string Ttitle
        {
            get;
        }
    }
}

 

 插件(单独的一个DLL):  继承插件接口,并且实现插件的方法, 完成后, 将编译后的dll文件, 拷贝到宿主运行的 plus目录下.

   

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using plusInterfaces;
using System.Windows.Forms;

namespace Plus
{
    public class Plc1 : plusUI
    {

        public Control GetUI()
        {
            Label l = new Label();
            l.Text = "这是一个Lable标签";
            return l;
        }

        public string Ttitle
        {
            get { return "这里显示TapPage的标题"; }
        }
    }
}
View Code

 

再说说宿主如何加载插件.

 在宿主页面的PageLoad 事件里面,  读取插件 dll,然后进行反射,然后执行  实现接口的方法和属性

  

private void Form1_Load(object sender, EventArgs e)
        {
            //启动时,动态加载插件
            string appPath = Application.ExecutablePath;//运行的路径
            string plusPath = appPath.Substring(0,appPath.LastIndexOf(@"\\"))+@"\\plus";
            string[] plusFileNames = Directory.GetFiles(plusPath,"*.dll");


            //解析 dll 看其是否实现了chajian接口
            foreach (string  filename in plusFileNames)
            {
                Assembly ass = Assembly.LoadFile(filename);

                Type[] types = ass.GetTypes();
                foreach (Type type in types)
                {
                    //判断type是否是插件
                    Type[] interFacesType = type.GetInterfaces();
                    foreach (Type typeInterface in interFacesType)
                    {
                        if (typeInterface.FullName=="plusInterfaces.plusUI")
                        {
                            //实现该类的接口,就是插件
                            plusUI plus = (plusUI)Activator.CreateInstance(type);

                            Control control = plus.GetUI();
                            control.Dock = DockStyle.Fill;
                            TabPage page = new TabPage();
                            page.Text = plus.Ttitle;
                            page.Controls.Add(control);
                            this.tbcontr.TabPages.Add(page);
                        }
                    }
                }
            }

        }

 

现在直接运行宿主, 就能加载插件了. 

 示例下载:   WinHostPlus

以上是关于宿主插件模式的主要内容,如果未能解决你的问题,请参考以下文章

VIM 代码片段插件 ultisnips 使用教程

WordPress - 代码片段插件

如何从 Qt 插件中使用宿主应用程序的类?

VSCode插件开发全攻略代码片段设置自定义欢迎页

Wordpress - 将代码片段包含到布局的选定部分的插件

Word 文档的优秀代码片段工具或插件?