C#_Assembly-Reflection_程序集与反射 练习<一> 记事本插件编写
//MyNotepad 为其编写插件 动态加载 听起来很niuB有木有?^_~ 下面我们就来实现这个吧!加油
//新建工程 添加窗体项目 画如下界面:
//这里有个菜单项 以及TextBox -> Dock填充中间
//这里先实现 窗体加载时 动态加载dll(所谓的插件)到菜单栏中
//我们在Debug目录下(改目录可以修改) 创建放置我们插件的地方 就新建一个文件夹 就叫Plugins吧
jiangzi:
现在我们假设在Plugins文件夹中已经有了我们写好的接口文件(稍后我们再去编写这个文件)
我们在程序加载时去动态加载这个文件夹下的所有dll文件
1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 } 7 8 private void Form1_Load(object sender, EventArgs e) 9 { 10 LoadPlugins(); 11 } 12 private void LoadPlugins() 13 { 14 15 //加载dll文件 : 1. 找到文件 2.加载 16 17 //get the directory 18 string dPath=Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 19 20 string pluginsDirectoryPath = Path.Combine(dPath, "Plugins"); 21 22 //find all dll files 23 string[] allDllFilePath = Directory.GetFiles(pluginsDirectoryPath, "*.dll"); 24 25 //遍历每个dll文件 动态加载到程序集中 26 for (int i = 0; i < allDllFilePath.Length; i++) 27 { 28 Assembly assembly = Assembly.LoadFile(allDllFilePath[i].ToString()); 29 //利用反射获取类型 30 Type[] types = assembly.GetTypes(); 31 //遍历types中所有类型 找到我们所需要的类型 32 //那我们需要什么类型呢? 33 } 34 } 35 }
//那我们需要什么类型呢? ---->> 使用接口来规范我们将要用的类型
好哒,我们现在在工程中添加接口文件 (其实就是添加一个类啦~)
jiangzi:
在IEditor.cs文件中定义我们的接口规范:
1 public interface IEditor 2 { 3 //定义一个只读属性 表示插件的名称 4 public string PluginName 5 { 6 get; 7 } 8 //运行该插件的方法 9 void Run(TextBox txtBox); 10 }
//有了接口规范 我们现在就去写我们之前假设有(实际上没有)的dll文件吧,吼吼~
添加类库,这里我们把插件实现的功能写在这个类库中 要实现我们刚才定义的接口规范 记得引用接口哟~
jiangzi:
我们在使在插件中定义的类型去继承接口 :
1 public class ToUpper:IEditor 2 { 3 //实现接口中定义的只读属性 4 string PluginName 5 { 6 get { return "转换大写"; } 7 } 8 9 //实现接口中定义的函数 10 public void Run(System.Windows.Forms.TextBox txtBox) 11 { 12 txtBox.Text = txtBox.Text.ToUpper(); 13 } 14 }
//在主窗体中继续:
1 //遍历每个dll文件 动态加载到程序集中 2 for (int i = 0; i < allDllFilePath.Length; i++) 3 { 4 Assembly assembly = Assembly.LoadFile(allDllFilePath[i].ToString()); 5 //利用反射获取类型 6 Type[] types = assembly.GetTypes(); 7 8 //那我们需要什么类型呢? //在接口中去定义 9 10 //我们期望获取的接口类型 11 Type IEditorType=typeof(IEditor); 12 13 //遍历types中所有类型 找到我们所需要的类型 14 for (int j = 0; j < types.Length; j++) 15 { 16 //判断 1.是IEditorType的实例 2.不为抽象类型 17 if (IEditorType.IsAssignableFrom(types[j]) && !types[j].IsAbstract) 18 { 19 //找到类型之后 为接口变量 赋值 --> 实现该接口的类型的对象 20 IEditor ieditor = (IEditor)Activator.CreateInstance(types[j]); 21 22 //将插件名称加载到该格式下拉表中 23 ToolStripItem tsp= MenuStripItemFormat.DropDownItems.Add(ieditor.PluginName); 24 25 //为tsp注册事件 26 tsp.Click += tsp_Click; 27 tsp.Tag = ieditor; 28 } 29 } 30 }
//为单击注册的事件:
1 void tsp_Click(object sender, EventArgs e) 2 { 3 ToolStripItem tsp = sender as ToolStripItem; 4 IEditor ieditor = (IEditor)tsp.Tag; 5 if (ieditor != null) 6 { 7 ieditor.Run(this.textBox1); 8 } 9 }
ok~来运行下:发现菜单下啥都没有~
额~
因为还没把生成的插件放到文件夹下 程序找不到这个插件 自然不会去加载 二货 ^_ ~
好哒~我们来清理 重新生成下 将生成的dll文件放到主窗体中 我们定义的Plugins文件中:
jiangzi:
再次运行:
噢了~
下次插件继续~