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 ...
随机推荐
- Swing中的线程并发处理
理论解释见官方的文档: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html 一个Swing程序中一般有下面三种 ...
- NodeJS简单爬虫
NodeJS简单爬虫 最近一直在追火星的一本书,然后每次都要去网站看,感觉很麻烦,于是,想起用爬虫爬取章节,务实派,说干就干! 爬取思路 1.该网站的页面呈现出一定的规律 2.使用NodeJS的req ...
- gitlab服务部署及使用
一.什么是gitlib Gitlab 是一个基于Git实现的在线代码仓库托管软件,你可以用Gitlab自己搭建一个类似于Github一样的系统平台,一般搭建gitlab私服就是用在公司的内部 Gitl ...
- 测试工具之RobotFramework关键字和快捷键
RF中关键字很多,即使经常使用也有些关键字没有使用过,所以我们就需要记住一些常用的关键字,在使用中本人整理了部分关键字.快捷键和部分RF的常识 1.F5 如果只记得关键字部分,可以通过F5呼出关键字查 ...
- 关于vue中钩子函数非常好的博客
http://www.cnblogs.com/caimuqing/p/6728568.html
- 如何才能够系统地学习Java并发技术?
微信公众号[Java技术江湖]一位阿里Java工程师的技术小站 Java并发编程一直是Java程序员必须懂但又是很难懂的技术内容. 这里不仅仅是指使用简单的多线程编程,或者使用juc的某个类.当然这些 ...
- 【Java基本功】很多人经常忽视的Java基础知识点
*.Java文件 问题:一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 答案:可以有多个类,但只能有一个public的类,并且public的类名必须与文件 ...
- MySQL 一些内部原理
1. MySQL 体系结构 如下图: Mysql是由SQL接口,解析器,优化器,缓存,存储引擎组成的(SQL Interface. Parser. Optimizer.Caches&Buffe ...
- 基于vue2.0实现仿百度前端分页效果(一)
前言 最近在接手一个后台管理项目的时候,由于之前是使用jquery+bootstrap做的,后端使用php yii框架,前后端耦合在一起,所以接手过来之后通过vue进行改造,但依然继续使用的boots ...
- ThreadLocalMap里Entry为何声明为WeakReference?
Java里,每个线程都有自己的ThreadLocalMap,里边存着自己私有的对象.Map的Entry里,key为ThreadLocal对象,value即为私有对象T.在spring MVC中,常用T ...