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 下载,就可以直接使用了,以前的接口都定义好了,新的实现类也就是不可预料的,因此不能在主程序实例化实现接口的类,这样违背了插件的初衷。

时间: 2024-09-20 18:35:39

C# 插件式程序开发的相关文章

插件式框架开发的优势劣势

问题描述 插件式开发的优势不用说了,楼主有个工业上位机的小项目基本做得差不多了,和下位机用串口和以太网通信.现在想把两种通信做成主程序的插件(看起来高端也有其他好处)但是众所周知,插件是根据主程序的接口来实现的,我想问下这样可移植性不就低了吗?假如别的部门需要我的串口通信插件,他们的主程序得弄个跟我插件一样的接口先,对吗?另外我们后面想用第三方控件重做UI,UI层能用插件来优化更新吗?就是插件改变UI的意思插件也是继承接口的类库编成dll文件给别人用,那直接写一个类变成dll文件,别人用里面的方

构建插件式的应用程序框架(一)-开篇

说起插件(plug-in)式的应用程序大家应该不陌生吧,记得很早以前有一款很流行的MP3播放软件winmap,它是我记忆里最早认识的一款使用插件模式的应用程序,你可以使用他的插件管理器插入很多的音乐效果器,皮肤,甚至是歌词显示的面板.接下来看到了Photoshop使用插件模式管理虑镜.最后发现只要是大一点的应用程序基本都使用了插件式的程序框架,就拿我们最常用的工具来说吧,Visual Studio,Office,Delphi,Eclipse等等.Eclipse将插件模式发挥到了及至,因为他是开源

构建插件式的应用程序框架(四)-服务容器

IApplication接口是派生于IServiceContainer接口的.为什么要派生于IServiceContainer呢?我们来看看IServiceContainer的定义,它有几个AddService方法和RemoveService方法以及从IserviceProvider继承过来的GetService方法.Service本身是.NET设计时架构的基础,Service提供设计时对象访问某项功能的方法实现,说起来还真拗口.就我看来,ServiceContainer机制的本质就是解耦合,就

插件框架 osgi mef-想请教下大神们插件式开发有什么好的插件框架?

问题描述 想请教下大神们插件式开发有什么好的插件框架? 我目前知道的有osgi,微软的maf.mef.除此之外还有些什么框架?还有目前应用最广泛的是什么框架 解决方案 Unity和MEF因为是微软出的,用的比较多一些.其实单纯插件系统,自己用反射就可以实现了.这些框架严格来说,是用于比较复杂的依赖注入(dependency injection)的.当然,插件系统也可以算依赖注入的一个用例. 解决方案二: dll plugin算不算 解决方案三: Unity Autofac Ninject Str

现完成了一套插件式构架的程序,用VS2005打包,能不能做到安装时选择了那些插件,才把相应插件的DLL安装进客户机去?

问题描述 现完成了一套插件式构架的程序,用VS2005打包,能不能做到安装时选择了那些插件,才把相应插件的DLL安装进客户机去? 解决方案 解决方案二:有人知道嘛?或者提下思路也好啊......解决方案三:顶上去..........解决方案四: 解决方案五:没人知道嘛?还是.NET自己打包,没法实现这种功能?一定要先把所以的DLL文件都COPY到客户机的?解决方案六:小顶一下解决方案七:可能你要自己在Setup程序里面写自定义的安装步骤,没写过具体也没办法告诉你你可以考虑InstallShiel

jquery-jQuery插件式开发与直接页面写JS的思想转换?

问题描述 jQuery插件式开发与直接页面写JS的思想转换? 用插件式开发 (function($){ $.fn.extend({ "ui.person.personlist.page" :function() { } } }); $(document).ready(function(){ var mainpage=$("#")["ui.person.personlist.page"](); mainpage.init(); }); })(jQu

eclipse插件开发-swt插件程序开发的问题

问题描述 swt插件程序开发的问题 再用swt开发桌面客户端应用程序时,显示的图片放入到标签中还是面板中呢?还有怎么实现一个购物车的功能,求高人指点一下?

构建插件式的应用程序框架(一)----订立契约

问题描述 无论是用COM的方式,还是普通DLL,抑或.NET方式来实现插件框架,首先要面临的问题就是如何订立契约.如同我上一篇文章讲到的一样,契约是应用程序和插件之间进行交互的依据和凭证.应用程序必须声明我有什么样的功能可被插件使用,并且插件必须符合什么条件才能被我使用.反之,插件必须要知道应用程序提供什么样的功能,我才能将自己的功能融入到应用程序的体系中.本系列文章主要讲如何使用.NET实现插件式的应用程序框架,所以其它的方式我就不再提了.如何使用.NET订立契约呢?首先想到的Interfac

构建插件式的应用程序框架(五)-管理插件

我们现在已经搭建了插件式的应用程序框架,接下来的工作就是要充实框架的内容,提供基本的服务,也就是Service.我想首要的任务就是提供插件的管理服务,我在前面的文章也提到了,要实现动态加载必须要知道插件寄宿在哪里,哪些要加载,哪些不加载,这些就是这篇文章要讨论的问题. 首先解决的就是插件放在什么地方,我采取的传统的方法,将插件放到应用程序所在目录下的制定目录,我会在应用程序所在的目录下创建一个文件夹,命名为Plugins.接下来的工作就是要通知哪些插件是要加载的,哪些是不需要加载的,我会将这些信