zoukankan      html  css  js  c++  java
  • 宿主插件模式

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

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

        我这里先说一下"宿主", 宿主一般作为一个启动器,可以有一些基础的功能,也可以没有, 宿主提供统一的接口, 对外的插件实现该接口, 然后宿主通过加载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

  • 相关阅读:
    mysql主从配置
    前台使用复杂json
    eclipse打包非web项目的整合了spring和mybaits的pom项目,打包可以运行的jar
    Select
    sqlcmd踩坑笔记(环境Ubuntu18.04)
    等待
    戴锦华访谈:小鲜肉 大女主 腐文化的流行 当代女性的生存现状和困境
    CREATE
    语法约定和标识符
    SQL Server应用目录
  • 原文地址:https://www.cnblogs.com/mjxxsc/p/7457367.html
Copyright © 2011-2022 走看看