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 ...
随机推荐
- Android NDK学习(四):C/C++层调用JAVA
一.从C/C++层调用JAVA层代码(无参数调用) //在c代码里面调用java代码里面的方法 // java 反射 // 1 . 找到java代码的 class文件 // jclass (*Find ...
- WebRTC学习之 Intel® Collaboration Suite for WebRTC源码流程解读
年后回来,因为新项目的需求,开始了解WebRTC相关的知识.目前接触的是Intel® Collaboration Suite for WebRTC.刚开始看SDK发现很多概念是我目前不知道的,于是恶补 ...
- Linux - 参考链接
01 - Linux系统监控的Shell脚本 常用的主机监控Shell脚本 使用Shell脚本对Linux系统和进程资源进行监控 02 - Linux系统结构 Linux 系统结构详解 03 - Li ...
- django rest framework serializers解读
serializers是什么?官网是这样的"Serializers allow complex data such as querysets and model instances to b ...
- 【xsy1303】生成树 乱搞
题目大意:给你n个点,问这n个点构成的最小标准差生成树的值 这题题解里面写的都是什么代码?? 你用O(n^4)的复杂度,枚举出两条边,然后求平均数. 对于剩下的边,我们求出这些边与平均数的差,然后求最 ...
- spring cloud+.net core搭建微服务架构:Api授权认证(六)
前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...
- 国外程序员整理的 C++ 资源大全 (zt)
关于 C++ 框架.库和资源的一些汇总列表,由 fffaraz 发起和维护. 内容包括:标准库.Web应用框架.人工智能.数据库.图片处理.机器学习.日志.代码分析等. 标准库 C++标准库,包括了S ...
- 获取 BaiduMapSDKDemo SHA1 签名
用 Android Studio 1.5 运行 BaiduMapsApiASDemo 时,显示 key 验证出错. 原因在于用 keytool -list -keystore debug.keysto ...
- 逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理
逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理 一丶透视简介 我们涉及到FPS游戏.免不了说透视.自瞄什么的. 在CS1.6中. 有OpenGl.也有D3D. 透视的方法很多. gl透视(也 ...
- Storm 性能优化
目录 场景假设 调优步骤和方法 Storm 的部分特性 Storm 并行度 Storm 消息机制 Storm UI 解析 性能优化 场景假设 在介绍 Storm 的性能调优方法之前,假设一个场景:项目 ...