接着上一篇文章:
MEF:
原文:
首先,新建一个类库,里面定义接口,这里定义两个方法,一个有返回值的,一个无返回值的。
using System; using System.Collections.Generic; using System.Text; namespace IMsg { ////// 这是插件必须实现的接口,也是主程序与插件通信的唯一接口 /// 换句话说,主程序只认识插件里的这些方法 /// publicinterface IMsgPlug { void OnShowDlg(); string OnShowInfo(); } }
using System; using System.Collections.Generic; using System.Text; using IMsg; namespace MYPlugin1 { publicclass myConsole: IMsgPlug { #region IMsgPlug成员publicvoid OnShowDlg() { Console.WriteLine("控制台调用插件的OnShowDlg方法"); } publicstring OnShowInfo() { return "myConsole"; }#endregion } } using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using IMsg; namespace MYPlugin1 { publicclass MYDlg: Form, IMsgPlug { #region IMsgPlug成员 publicvoid OnShowDlg() { this.Text = "插件子窗体"; this.ShowDialog(); //调用Form的ShowDialog,显示窗体 } publicstring OnShowInfo() { return "MyDlg"; }#endregion } }
将上面的都生成dll, 生成目录可以设置为新建exe工程的bin目录plugins文件夹下。Plugins文件夹是新建的,专门存放插件的。 新建一个 WinForm项目来使用刚才的插件.
using System; using System.IO; using System.Linq; using System.Collections; using System.Windows.Forms; using System.Reflection; namespace myConsole { public partial class Form1 : Form { ////// 应用程序的主入口点。 /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } public Form1() { InitializeComponent(); } ////// 存放插件的集合 /// private ArrayList plugins = new ArrayList(); //载入所有插件 private void btnLoadPlug_Click(object sender, EventArgs e) { string[] files = Directory.GetFiles(Application.StartupPath + "\\plugins"); if (files != null) this.listBox1.Items.Clear(); foreach (var f in files) { if (!f.ToUpper().EndsWith(".DLL")) continue; try { Assembly ab = Assembly.LoadFile(f); Type[] t = ab.GetTypes(); foreach (var x in t) { if (x.GetInterface("IMsgPlug") != null) { plugins.Add(ab.CreateInstance(x.FullName)); this.listBox1.Items.Add(x.FullName); } } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } //调用插件的方法 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(); } } }
运行结果:
此方法用了反射,个人感觉效果不是很好。另外,注意dll对象的依赖,这种问题我在手写上面demo的时候发现了,首先要保证依赖文件的存在,再一个依赖文件的路径需要正确。另一点要说下,对反射后的验证可以做一些加强处理,listbox对象显示的名字可以通过给dll中对象添加特性标记,然后获取显示出来。下一节我们看看MEF的小例子。
最后想说一下,这不是正在意义上的插件式开发,请参阅微软的MEF和MAF的设计
出处:http://blog.csdn.net/joyhen/article/details/40072973