在网上找了下插件式编程的资料,这里自己先借鉴下别人的,同时发现有自己的看法,不过由于本人水平有限,不一定有参考价值,写出来一方面是为了总结自己,以求提高,另一方面也希望各为朋友看到我的不足,给我提出宝贵意见。

什么是插件式编程

提起插件式,我们首先想到的是firefox,用过firefox的人都知道它是一个插件式程序。当一个功能需要,完全可以从网上下载一个插件后,重启后,就能使用。这个功能给我们带来许多的方便之处,这就是插件式程序的好处。

插件的本质在于不修改程序主体(平台)的情况下对软件功能进行拓展与加强,当插件的接口公开后,任何公司或个人都可以制作自己的插件来解决一些操作上的不便或增加新功能,也就是真正意义上实现“即插即用”软件开发。

平台+插件软件结构是将一个待开发的目标软件分为两部分,一部分为软件的主体或框架,可定义为平台,这是预先编译后的程序。另一部分为功能或补充模块,可定义为插件。这个就是后来要进行安装的插件程序。

假设你的程序已经部署在用户的计算机上,并且能够正常运行了。但是有一天,用户打来电话——他们需要增加新的功能。确定了用户的需求后,你竟然发现原有的软件架构已经无法胜任新增任务的需求——你需要重新设计这个应用了!但问题是,就算你又用了一个开发周期完成了用户需要的应用,切不能保证用户的需求不会再次变更。也就是说,需求蔓延的可能性依然存在。因此,这种情况下插件架构更能显示出它的优越性。

可以这么说,用它可以带来方便的地方,而且开发它,也很简单。而且这样的主程序根本就不需要改动。需要插件时,拿来就能用,插件更新时,也只需更新这个插件即可。

从程序开发这角度,一般是先开发主程序,决定哪些功能由主程序来完成,然后再建立接口,申明接口的内容,这些内容决定着插件功能的扩展,及方向的。这些都是有主程序开发者预先准备好的。插件开发者,从主程序开发者那里得到接口的内容,并书写继承这些接口的类,来完成具体的功能。

下面来写个例子,这个例子没实际意义,纯属学习思想。例子是网上的经过自己改造的,发现别人某些地方不合理。

首先,新建一个类库,里面定义接口,这里定义两个方法,一个有返回值的,一个无返回值的。


using System;using System.Collections.Generic;using System.Text;namespace IMsg{    /// <summary>    /// 这是插件必须实现的接口,也是主程序与插件通信的唯一接口    /// 换句话说,主程序只认识插件里的这些方法    /// </summary>  public  interface IMsgPlug    {        void OnShowDlg();        string OnShowInfo();    }}

将上面的类库生成IMsg.dll,新建一个类库MYPlugin1,添加刚出的引用,分别新建两个类来实现IMsg中定义的接口。


    using System;using System.Collections.Generic;using System.Text;using IMsg;namespace MYPlugin1{    public class myConsole : IMsgPlug    {        #region IMsgPlug 成员        public  void OnShowDlg()        {            Console.WriteLine("控制台调用插件的OnShowDlg方法");        }        public  string OnShowInfo()        {            return "myConsole";        }        #endregion    }}using System;using System.Collections.Generic;using System.Text;using System.Windows.Forms;using IMsg;namespace MYPlugin1{ public  class MYDlg:Form,IMsgPlug    {        #region IMsgPlug 成员        public  void OnShowDlg()        {            this.Text = "插件子窗体";            this.ShowDialog();//调用Form的ShowDialog,显示窗体        }        public  string OnShowInfo()        {            return "MyDlg";        }        #endregion    }}

将上面的都生成dll,生成目录可以设置为新建exe工程的bin目录plugins文件夹下。Plugins文件夹是新建的,专门存放插件的。 新建一个 WinForm项目,来使用刚才的插件.


using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Collections;using System.IO;using System.Reflection;namespace MsgBoxMain{    public partial class FormMain : Form    {        /// <summary>        /// 存放插件的集合        /// </summary>        private ArrayList plugins = new ArrayList();        public FormMain()        {            InitializeComponent();        }        /// <summary>        /// 载入所有插件        /// </summary>        private void LoadAllPlugs()        {            //获取插件目录(plugins)下所有文件            string[] files = Directory.GetFiles(Application.StartupPath + @"\plugsins");            foreach (string file in files)            {                if (file.ToUpper().EndsWith(".DLL"))                {                    try                    {                        //载入dll                        Assembly ab = Assembly.LoadFrom(file);                        Type[] types = ab.GetTypes();                        foreach (Type t in types)                        {                           //如果某些类实现了预定义的IMsg.IMsgPlug接口,则认为该类适配与主程序(是主程序的插件)                            if (t.GetInterface("IMsgPlug")!=null)                            {                                plugins.Add(ab.CreateInstance(t.FullName));                                listBox1.Items.Add(t.FullName);                            }                        }                    }                    catch (Exception ex)                    {                        MessageBox.Show(ex.Message);                    }                }            }         }        private void btnLoadPlug_Click(object sender, EventArgs e)        {            LoadAllPlugs();        }        //调用插件的方法        private void btnExecute_Click(object sender, EventArgs e)        {            if (this.listBox1.SelectedIndex == -1) return;            object selObj = this.plugins[this.listBox1.SelectedIndex];            Type t = selObj.GetType();            MethodInfo OnShowDlg = t.GetMethod("OnShowDlg");            MethodInfo OnShowInfo = t.GetMethod("OnShowInfo");            OnShowDlg.Invoke(selObj, null);            object returnValue = OnShowInfo.Invoke(selObj, null);            this.lblMsg.Text = returnValue.ToString();                    }    }}

运行结果:

这里与网上那位原创的仁兄的看法不同(原文链接http://blog.csdn.net/jam12315/archive/2008/08/18/2791534.aspx),可供大家讨论。

原文有 这样的一段:

if (itemStr == "myConsole")
                {   //调用存储在动态数组plugins里面的插件对象的OnShowInfo方法
                    string msgInfo = ((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowInfo();
                    MessageBox.Show(msgInfo, "MYPlugin1", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else if (itemStr == "MYDlg")//调用存储在动态数组plugins里面的插件对象的OnShowDlg方法
                {
                    ((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowDlg();
                }

我认为既然是插件,就应该是动态加载的,客户端肯定不能判断 itemStr,因为实现接口的类是不可预料的,因此主程序不应该添加对IMsg的引用,也不应该在客户端实例化插件对象,因为插件开发的初衷是为了以后更新的时候不更改主程序,只提供对应的dll 下载,就可以直接使用了,以前的接口都定义好了,新的实现类也就是不可预料的,因此不能在主程序实例化实现接口的类,这样违背了插件的初衷。

C# 插件式开发的更多相关文章

  1. C#学习笔记-----基于AppDomain的"插件式"开发

    很多时候,我们都想使用(开发)USB式(热插拔)的应用,例如,开发一个WinForm应用,并且这个WinForm应用能允许开发人员定制扩展插件,又例如,我们可能维护着一个WinService管理系统, ...

  2. ctkPlugin插件系统实现项目插件式开发

    插件式开发体会: 自开始写[大话QT]系列就开始接触渲染客户端的开发,说是开发不如更多的说是维护以及重构,在接手这块的东西之前自己还有点犹豫,因为之前我一直认为客户端嘛,没什么技术含量,总是想做比较有 ...

  3. MVC 插件式开发

    MVC 插件式开发 在开发一个OA系统是,我们可能遇到 A模块. B模块 .C模块,这也模块组成一个完整的系统,买给客服.现在又有一个客服要我们做一个OA系统,唉我们发现,跟上一个OA系统差不多,但没 ...

  4. JQuery的插件式开发

    如果你只会JQuery的插件式开发, 那么你可以进来看看? 对于JQuery的学习,已经有3年多的时间了,直到去年与我的组长一起做项目,看到他写的JS,确实特别漂亮,有时甚至还看不太懂, 我才发现其实 ...

  5. .NET MVC 简单的插件式开发

    插件式开发的优势 1.提高软件的复用度 2.提高软件开发的并行性 3.缩短软件的研发周期.节约研发成本,带给程序开发人员更多的灵活性,产品在软件发布以后还可以添加新的插件和完善已有的功能. 4.方便软 ...

  6. 基于AppDomain的"插件式"开发

    很多时候,我们都想使用(开发)USB式(热插拔)的应用,例如,开发一个WinForm应用,并且这个WinForm应用能允许开发人员定制扩展插件,又例如,我们可能维护着一个WinService管理系统, ...

  7. 也来学学插件式开发续-利用MEF

    前面一个博客:也来学学插件式开发中很多朋友留言说可以用MEF来实现.于是我就试着用MEF实现了一下. 步骤和上一篇差不多,只是加载插件的方式有所不同.这只是一个自己的示例程序,肯定有很多不足之处,欢迎 ...

  8. MEF 插件式开发 - 小试牛刀

    原文:MEF 插件式开发 - 小试牛刀 目录 MEF 简介 实践出真知 面向接口编程 控制反转(IOC) 构建入门级 MEF 相关参考 MEF 简介 Managed Extensibility Fra ...

  9. MEF 插件式开发 - WPF 初体验

    原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场 ...

  10. 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用ApplicationPart动态加载控制器和视图

    标题:从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 作者:Lamond Lu 地址:http://www.cnblogs ...

随机推荐

  1. WebRTC学习之ICE深入理解

    ICE(交互式连接建立---Interactive Connectivity Establishment),是一种标准穿透协议.它利用STUN和TURN服务器来帮助端点建立连接.下图显示了ICE的基本 ...

  2. TI 开发板安装USB转串口驱动

    使用TI开发板的时候,USB转串口驱动没有,显示,无法识别设备.搜了好久才搜到相关驱动. 做个记录. 链接: https://pan.baidu.com/s/1ZT5zzVcU727jrYacKVoT ...

  3. spring boot 集成freemarker

  4. [视频]K8飞刀 SQL注入点脱库演示教程

    K8飞刀 SQL注入点脱库演示动画教程 链接:https://pan.baidu.com/s/15gLTxiv9v1Te5QNFZnfV4A 提取码:eaa1

  5. 13-03 Java 基本类型包装类概述,Integer类,Character

    基本类型包装类概述 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据.常用的操作之一:用于基本数据类型与字符串之间的转换.基本类型和包装类的对应Byte,Short,Inte ...

  6. 边缘化搭建 DotNet Core 2.1 自动化构建和部署环境(上)

    写在前面 写这篇文章的缘由是由于笔者的对新兴技术方向有所追求,但个人资产有限,只能容许购买一台阿里云低配1核2G服务器.服务器上搭建了 Centos7 & Docker & Jenki ...

  7. Spring Boot + Spring Cloud 实现权限管理系统 后端篇(十九):服务消费(Ribbon、Feign)

    技术背景 上一篇教程中,我们利用Consul注册中心,实现了服务的注册和发现功能,这一篇我们来聊聊服务的调用.单体应用中,代码可以直接依赖,在代码中直接调用即可,但在微服务架构是分布式架构,服务都运行 ...

  8. git第十节--git hub

    github 是一个开源的协作社区 github 插件octtree 为别人的仓库做贡献 fork 别人仓库内容到自己的个人仓库 git clone 到本地进行开发push 到个人仓库 提PR(pul ...

  9. SSM框架、Druid连接池实现多数据源配置(已上线使用)

    总体大概流程: 1.配置数据源.账密(账密一致,文章不多阐述) driverClassName = com.mysql.jdbc.Driver   validationQuery = SELECT 1 ...

  10. [USACO13DEC] Optimal Milking

    Description n个点排成一排,点有点权,要求支持两种操作: 修改某个点的点权 询问取出任意多且不相邻的点的点权和最大值 Solution 跟最大子段和一样,可以用分治做,用线段树记录一下左右 ...