宿主插件模式

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

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

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

    }

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

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的标题"; }
        }
    }
}

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

在宿主页面的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

时间: 2024-08-11 00:27:35

宿主插件模式的相关文章

基于.net 职责链来实现 插件模式

插件式的例子 QQ电脑管家,有很多工具列表,点一下工具下载后就可以开始使用了 eclipse ,X Server 等等 插件式的好处 插件降低框架的复杂性,把扩展功能从框架中剥离出来 让第三方有机会来扩展程序的功能 思路       公开一个插件接口,如果.DLL或.EXE的代码中有继承这个接口就将其示为插件,并将这些插件放在同一目录.运行程序的时候扫描目   录并通过反射判断.DLL或.EXE中是否存在该接口,若存在,则当作插件加载进来.如下图示   基于.net 职责链来实现 插件模式   

045-利用反射机制,简单的实现PHP插件模式

<?php //利用反射机制,简单的实现PHP插件模式 # 假设,我们有一款开源产品,所有开发者都必须在我定制的需求之上,进行二次开发, # 而开发完成后的新模块,就是一个不一样的新插件,可以放在特定的位置进行自动加载 #这是我们的开源产品 interface Demo{ # 所有插件都必须实现这个方法 public function msg(); } #这是小明开发的插件-1 class xiaoming implements Demo{ public function msg(){ echo

app微信支付宝支付后台的插件模式+回调通过spring广播处理后续业务(已亲测可用)

写在前面的话:每当我们做一个项目,基本上都会涉及到支付的业务,最常用的莫过于微信和支付宝的支付了,项目有bug,有问题,都不叫问题,可一旦钱出了问题,那就是大问题了,所以在支付业务上我们必须慎之又慎! 但是我们做开发的,并不是在一个项目中完成支付模块就万事大吉了,在下一个项目中,我们是不是又要将支付模块的代码复制粘贴一遍,然后再重改支付模块?这样的坏处是频繁修改支付模块难免出现一些我们自己都意识不到的问题,一旦暴露在一些不怀好心的又懂技术的人面前,那我们哭都不知道去找谁. 所以,我试着通过利用s

ueditor的优酷插件模式开发,目前开发了腾讯视频转换插件

项目相关地址 源码:https://github.com/easonjim/ueditor_plugin bug提交:https://github.com/easonjim/ueditor_plugin/issues

.NET简谈插件系统开发模式

摘选自[王清培]博客 http://www.cnblogs.com/wangiqngpei557/archive/2011/06/10/2077413.html 今天跟大家分享一下我们在日常开发中并不常用的开发模式“插件系统模式”,什么叫插件,从大一点的概念讲就是我们开发的软件是由很小的模块组成,每一块都能成功的装卸,使我们的软件成为一个有机体,在发生重大事故.改良优化等等的时候,我们不需要重新编译我们的系统就能很方便的进行升级替换进行使用:这样的开发模式就是插件系统开发模式:这个概念很大,每个

Android插件实例——360 DroidPlugin具体解释

在中国找到钱不难,但你的一个点子不意味着是一个创业.你谈一个再好的想法,比方我今天谈一个创意说,新浪为什么不收购GOOGLE呢?这个创意非常好.新浪一收购GOOGLE.是不是新浪就变成老大了?你从哪儿弄来钱?怎么去整合GOOGLE呢: 之前写过有关于Android 插件方向的文章,解析了一下Android的插件原理与执行方式.非常多小伙伴都问我.为什么不把我制作的插件放到Github上,让大家共享一下. 我仅仅能说.大哥啊,这个插件是我在公司研发的时候制作的,商业机密.不能开源啊. 刚好.近期逛

Android插件实例——360 DroidPlugin详解

在中国找到钱不难,但你的一个点子不意味着是一个创业.你谈一个再好的想法,比如我今天谈一个创意说,新浪为什么不收购GOOGLE呢?这个创意很好.新浪一收购GOOGLE,是不是新浪就变成老大了?你从哪儿弄来钱?怎么去整合GOOGLE呢: 之前写过有关于Android 插件方向的文章,解析了一下Android的插件原理与运行方式.很多小伙伴都问我,为什么不把我制作的插件放到Github上,让大家共享一下. 我只能说,大哥啊,这个插件是我在公司研发的时候制作的,商业机密,不能开源啊. 刚好,最近逛git

360动态加载的Android插件框架

github地址:https://github.com/Qihoo360/DroidPlugin DroidPlugin 是360手机助手在Android系统上实现了一种新的插件机制:它可以在无需安装.修改的情况下运行APK文件,此机制对改进大型APP的架构,实现多团队协作开发具有一定的好处. 定义: HOST程序:插件的宿主. 插件:免安装运行的APK 限制和缺陷: 无法在插件中发送具有自定义资源的Notification,例如: a. 带自定义RemoteLayout的Notificatio

插件开发之360 DroidPlugin源码分析(五)Service预注册占坑

请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52264977 在了解系统的activity,service,broadcastReceiver的启动过程后,今天将分析下360 DroidPlugin是如何预注册占坑的?本篇文章主要分析Service预注册占坑,Service占了坑后又是什么时候开始瞒天过海欺骗AMS的?先看下Agenda: AndroidMainfest.xml中概览 Service中关键方法被h