C# 插件式程序开发
什么是插件式编程
提起插件式,我们首先想到的是firefox, 用过firefox的人都知道它是一个插件式程序。当一个功能需要,完全可以从网上下载一个插件后,重启后,就能使用。这个功能给我们带来许多的方便之处,这就是插件式程序的好处。
插件的本质在于不修改程序主体(平台)的情况下对软件功能进行拓展与加强,当插件的接口公开后,任何公司或个人都可以制作自己的插件来解决一些操作上的不便或增加新功能,也就是真正意义上实现“即插即用”软件开发。
平台+插件软件结构是将一个待开发的目标软件分为两部分,一部分为软件的主体或框架,可定义为平台,这是预先编译后的程序。另一部分为功能或补充模块,可定义为插件。这个就是后来要进行安装的插件程序。
假设你的程序已经部署在用户的计算机上,并且能够正常运行了。但是有一天,用户打来电话——他们需要增加新的功能。确定了用户的需求后,你竟然发现原有的软件架构已经无法胜任新增任务的需求——你需要重新设计这个应用了!但问题是,就算你又用了一个开发周期完成了用户需要的应用,切不能保证用户的需求不会再次变更。也就是说,需求蔓延的可能性依然存在。因此,这种情况下插件架构更能显示出它的优越性。
可以这么说,用它可以带来方便的地方,而且开发它,也很简单。而且这样的主程序根本就不需要改动。需要插件时,拿来就能用,插件更新时,也只需更新这个插件即可。
从程序开发这角度,一般是先开发主程序,决定哪些功能由主程序来完成,然后再建立接口,申明接口的内容,这些内容决定着插件功能的扩展及方向的。这些都是有主程序开发者预先准备好的。插件开发者,从主程序开发者那里得到接口的内容,并书写继承这些接口的类,来完成具体的功能。
下面来写个例子,这个例子没实际意义,纯属学习思想。例子是网上的经过自己改造的,发现别人某些地方不合理。
首先,新建一个类库,里面定义接口,这里定义两个方法,一个有返回值的,一个无返回值的。
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace IMsg 6 { 7 ///<summary> 8 /// 这是插件必须实现的接口,也是主程序与插件通信的唯一接口 9 /// 换句话说,主程序只认识插件里的这些方法 10 ///</summary> 11 publicinterface IMsgPlug 12 { 13 void OnShowDlg(); 14 string OnShowInfo(); 15 } 16 }
将上面的类库生成IMsg.dll, 新建一个类库MYPlugin1,添加刚出的引用,分别新建两个类来实现IMsg中定义的接口。
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using IMsg; 5 namespace MYPlugin1 6 { 7 publicclass myConsole : IMsgPlug 8 { 9 #region IMsgPlug 成员 10 publicvoid OnShowDlg() 11 { 12 Console.WriteLine("控制台调用插件的OnShowDlg方法"); 13 } 14 publicstring OnShowInfo() 15 { 16 return"myConsole"; 17 } 18 #endregion 19 } 20 } 21 22 using System; 23 using System.Collections.Generic; 24 using System.Text; 25 using System.Windows.Forms; 26 using IMsg; 27 namespace MYPlugin1 28 { 29 publicclass MYDlg:Form,IMsgPlug 30 { 31 #region IMsgPlug 成员 32 33 publicvoid OnShowDlg() 34 { 35 this.Text ="插件子窗体"; 36 this.ShowDialog();//调用Form的ShowDialog,显示窗体 37 } 38 publicstring OnShowInfo() 39 { 40 return"MyDlg"; 41 } 42 #endregion 43 } 44 }
将上面的都生成dll, 生成目录可以设置为新建exe工程的bin目录plugins文件夹下。Plugins文件夹是新建的,专门存放插件的。 新建一个 WinForm项目来使用刚才的插件.
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 9 using System.Collections; 10 using System.IO; 11 using System.Reflection; 12 namespace MsgBoxMain 13 { 14 publicpartialclass FormMain : Form 15 { 16 17 ///<summary> 18 /// 存放插件的集合 19 ///</summary> 20 private ArrayList plugins =new ArrayList(); 21 public FormMain() 22 { 23 InitializeComponent(); 24 } 25 26 ///<summary> 27 /// 载入所有插件 28 ///</summary> 29 privatevoid LoadAllPlugs() 30 { 31 //获取插件目录(plugins)下所有文件 32 string[] files = Directory.GetFiles(Application.StartupPath +@"\plugsins"); 33 foreach (string file in files) 34 { 35 if (file.ToUpper().EndsWith(".DLL")) 36 { 37 try 38 { 39 //载入dll 40 Assembly ab = Assembly.LoadFrom(file); 41 Type[] types = ab.GetTypes(); 42 foreach (Type t in types) 43 { 44 //如果某些类实现了预定义的IMsg.IMsgPlug接口,则认为该类适配与主程序(是主程序的插件) 45 if (t.GetInterface("IMsgPlug")!=null) 46 { 47 plugins.Add(ab.CreateInstance(t.FullName)); 48 listBox1.Items.Add(t.FullName); 49 } 50 } 51 } 52 catch (Exception ex) 53 { 54 MessageBox.Show(ex.Message); 55 } 56 } 57 } 58 } 59 60 privatevoid btnLoadPlug_Click(object sender, EventArgs e) 61 { 62 LoadAllPlugs(); 63 } 64 65 //调用插件的方法 66 privatevoid btnExecute_Click(object sender, EventArgs e) 67 { 68 if (this.listBox1.SelectedIndex ==-1) return; 69 object selObj =this.plugins[this.listBox1.SelectedIndex]; 70 Type t = selObj.GetType(); 71 MethodInfo OnShowDlg = t.GetMethod("OnShowDlg"); 72 MethodInfo OnShowInfo = t.GetMethod("OnShowInfo"); 73 74 OnShowDlg.Invoke(selObj, null); 75 object returnValue = OnShowInfo.Invoke(selObj, null); 76 this.lblMsg.Text = returnValue.ToString(); 77 78 } 79 } 80 }
运行结果:
转自:http://kb.cnblogs.com/page/104235/