C# 插件式开发
在网上找了下插件式编程的资料,这里自己先借鉴下别人的,同时发现有自己的看法,不过由于本人水平有限,不一定有参考价值,写出来一方面是为了总结自己,以求提高,另一方面也希望各为朋友看到我的不足,给我提出宝贵意见。
什么是插件式编程
提起插件式,我们首先想到的是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# 插件式开发的更多相关文章
- C#学习笔记-----基于AppDomain的"插件式"开发
很多时候,我们都想使用(开发)USB式(热插拔)的应用,例如,开发一个WinForm应用,并且这个WinForm应用能允许开发人员定制扩展插件,又例如,我们可能维护着一个WinService管理系统, ...
- ctkPlugin插件系统实现项目插件式开发
插件式开发体会: 自开始写[大话QT]系列就开始接触渲染客户端的开发,说是开发不如更多的说是维护以及重构,在接手这块的东西之前自己还有点犹豫,因为之前我一直认为客户端嘛,没什么技术含量,总是想做比较有 ...
- MVC 插件式开发
MVC 插件式开发 在开发一个OA系统是,我们可能遇到 A模块. B模块 .C模块,这也模块组成一个完整的系统,买给客服.现在又有一个客服要我们做一个OA系统,唉我们发现,跟上一个OA系统差不多,但没 ...
- JQuery的插件式开发
如果你只会JQuery的插件式开发, 那么你可以进来看看? 对于JQuery的学习,已经有3年多的时间了,直到去年与我的组长一起做项目,看到他写的JS,确实特别漂亮,有时甚至还看不太懂, 我才发现其实 ...
- .NET MVC 简单的插件式开发
插件式开发的优势 1.提高软件的复用度 2.提高软件开发的并行性 3.缩短软件的研发周期.节约研发成本,带给程序开发人员更多的灵活性,产品在软件发布以后还可以添加新的插件和完善已有的功能. 4.方便软 ...
- 基于AppDomain的"插件式"开发
很多时候,我们都想使用(开发)USB式(热插拔)的应用,例如,开发一个WinForm应用,并且这个WinForm应用能允许开发人员定制扩展插件,又例如,我们可能维护着一个WinService管理系统, ...
- 也来学学插件式开发续-利用MEF
前面一个博客:也来学学插件式开发中很多朋友留言说可以用MEF来实现.于是我就试着用MEF实现了一下. 步骤和上一篇差不多,只是加载插件的方式有所不同.这只是一个自己的示例程序,肯定有很多不足之处,欢迎 ...
- MEF 插件式开发 - 小试牛刀
原文:MEF 插件式开发 - 小试牛刀 目录 MEF 简介 实践出真知 面向接口编程 控制反转(IOC) 构建入门级 MEF 相关参考 MEF 简介 Managed Extensibility Fra ...
- MEF 插件式开发 - WPF 初体验
原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用ApplicationPart动态加载控制器和视图
标题:从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 作者:Lamond Lu 地址:http://www.cnblogs ...
随机推荐
- WebRTC 学习之 Conference 实现混音混屏
混音 混音的意义就是将多个音频流混成一路音频,在Conference 的实现中有分为终端实现和服务器实现. 1. 终端混音实现: 终端接受到多路(一般是多个用户)的音频流之后,在终端本地将多路音频流混 ...
- windows上xshell6的安装
各位大兄弟,好用的xshell组件来了,话不多说,开搞. 软件链接链接:https://pan.baidu.com/s/1vcRo2L-LNe2BrJ9-VCy57A 密码:ei73 有下面四个软件, ...
- windows phone开发-windows azure mobile service使用入门
在使用azure之前,我一直只能做本地app,或者使用第三方提供的api,尽管大多数情况下够用,但是仍不能随心所欲操纵数据,这种感觉不是特别好.于是在azure发布后,我就尝试使用azure来做为个人 ...
- win10 + gluon + GPU
1. 下载教程 可以用浏览器下载zip格式并解压,在解压目录文件资源管理器的地址栏输入cmd进入命令行模式. 也可以 git pull https://github.com/mli/gluon-tut ...
- Git本地上传到服务器
Git本地上传到服务器 2018年05月17日 10:45:02 VV-King 阅读数:643 标签: git 1.本机window系统的话先下载msysgit 下载后在开始菜单里面找到 &q ...
- jquery的contains方法
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- Ocelot 使用
官方文档:http://ocelot.readthedocs.io/en/latest/introduction/gettingstarted.html 新建两个Asp.net core API项目 ...
- Hystrix隔离策略
Hystrix的资源隔离策略分为两种:线程池和信号量.说到资源隔离,我们就要明白为什么需要资源隔离. 在一个分布式系统中,服务之间都是相互调用的,如下图所示:例如,我们容器(Tomcat)配置的线程个 ...
- JAVA 面试知识点
参考:https://www.cnblogs.com/java1024/p/8594784.html 反射: JAVA反射机制是在运行状态中, 对于任意一个类,都能够知道这个类的所有属性和方法: 对于 ...
- windows下mongodb基础玩法系列二CURD附加一
windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) windows下 ...