1、接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PlugDemo { public interface IPlugToText { string ProccessText(string text); } }
2、菜单属性Class
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PlugDemo { public class MenuNameAttribute:Attribute { private string _name; public string Name { get { return _name; } set { _name = value; } } public MenuNameAttribute(string name) { this._name = name; } } }
3、实现接口的实现类
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ComPlugDemo { [PlugDemo.MenuName("转小写")] public class PlugToLower : PlugDemo.IPlugToText { #region IPlugToText 成员 public string ProccessText(string text) { return text.ToLower(); } #endregion } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ComPlugDemo { [PlugDemo.MenuName("转大写")] public class PlugToUpper:PlugDemo.IPlugToText { #region IPlugToText 成员 public string ProccessText(string text) { return text.ToUpper(); } #endregion } }
4、反射机制:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Reflection; using System.IO; using PlugDemo; namespace 插件Demo { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { AddPlugMenu(); } void AddPlugMenu() { //1、加载正在运行的程序集的物理路径 Assembly ass = this.GetType().Assembly; string location = ass.Location; //2、获取 程序集所在文件夹,并转成 插件程序集文件夹的路径 string assDir = Path.GetDirectoryName(location); string plugDir = assDir + "\\plugs"; //3、扫描 产检文件夹里的 所有程序集文件 string [] dllPaths = Directory.GetFiles(plugDir,"*.dll"); //重点: 获取插件接口 类型对象 //4、遍历程序集文件路径,并加载程序家到内存中 Type iplugType = typeof(IPlugToText); foreach (string dllPath in dllPaths) { //4.1 、根据路径 加载程序集文件 到内存中 Assembly amy = Assembly.LoadFrom(dllPath); //4.2 、判断程序集中是否有插件类 //4.2.1、获取插件程序集里公有的类 Type[] types = amy.GetExportedTypes(); //4.2.2 循环遍历 插件程序集里的类型 ,判断是否实现记事本插件接口 foreach (Type t in types) { //判断 t 是否 实现了接口 IPlugToUpper if (iplugType.IsAssignableFrom(t)) { //重要,获取的MenuNameAttribute 特性对象,或将 内部的Name现在到菜单中 object[] atts = t.GetCustomAttributes(typeof(MenuNameAttribute),false); MenuNameAttribute menuName = atts[0] as MenuNameAttribute; //重要:根据插件类型,创建 插件类 对象 IPlugToText iplug = Activator.CreateInstance(t) as IPlugToText; ToolStripMenuItem item = new ToolStripMenuItem(menuName.Name); plugMenu.DropDownItems.Add(item); item.Click += new EventHandler(item_Click); item.Tag = iplug; } } } } void item_Click(object sender, EventArgs e) { ToolStripMenuItem item = sender as ToolStripMenuItem; IPlugToText iplug = item.Tag as IPlugToText; textBox1.Text = iplug.ProccessText(textBox1.Text); } } }