一 反射机制简介
反射,英文名称为reflection,有审查元数据并收集关于它的类型信息的能力。有关其定义,这里不做详细地介绍,接下来通过一个demo来解释如何利用反射搭建可扩展程序。
二 Talk 模块
1. 程序组成结构分为:Plug文件夹用于存储插件集dll,Config.txt配置文档配置所需要的插件集,exe文件,如图。
2. 功能介绍:通过配置Config文件动态实现Winform添加
或删除功能按钮。
3. 效果展示,当Config.txt内设置为下图时,Winform界面会自动创建两个按钮,点击“Tom”,出现弹窗。
当Config.txt中只有Luna这一项时,Windows界面对应只有一个“Luna”按钮。
4. 实现过程
4.1 首先创建一个父类类库工程(ProTalk),创建类Talk,类内声明一个type属性用于标记继承类;声明一个方法,用于功能实现。
namespace ProTalk { public abstract class Talk { public abstract string type { get; } public abstract string getTalkContext(); } }
4.2 创建实现反射的类库工程(ProTalkFactory),注意要引用ProTalk类库,定义静态方法用于获取所有继承父类的子类。
using System; using ProTalk; using System.IO; using System.Reflection; namespace ProTalkFactory { public class TalkFactory { // 返回父类(装有子类) public static Talk GetTalk(string type) { Talk talk = null; //动态获得程序集 string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plug"); string[] files = Directory.GetFiles(path, "*.dll"); foreach (string item in files) { Assembly ass = Assembly.LoadFile(item); //得到公开的数据类型 Type[] types = ass.GetExportedTypes(); foreach (Type t in types) { //创建子类对象,赋值给 talk if (t.IsSubclassOf(typeof(Talk)) && !t.IsAbstract) { talk = (Talk)Activator.CreateInstance(t); if (type == talk.type) { return talk; } else { talk = null; } } } } return talk; } } }
4.3 创建继承类类库工程(ProTom、ProLuna),type属性用于Config.txt配置
using ProTalk; namespace ProTom { public class Tom:Talk { public override string type { get { return "Tom"; } } public override string getTalkContext() { return "Tom: Hello,I am Tom!"; } } }
4.4 创建winform应用程序,注意引用ProFactory.dll及ProTalk.dll在生成的exe根目录下创建Plug文件夹及Config.txt文件。
实现核心代码:
private void Form1_Load(object sender, EventArgs e) { string[] lines = File.ReadAllLines("Config.txt"); int x = 139; int y = 154; foreach (var item in lines) { Button btn = new Button(); btn.Location = new Point(x, y); btn.Size = new Size(75, 23); x += 80; btn.Text = item; btn.Click += btn_Click; this.Controls.Add(btn); } } private void btn_Click(object sender, EventArgs e) { Button btn = sender as Button; try { Talk talk = TalkFactory.GetTalk(btn.Text); if (talk != null) { MessageBox.Show(talk.getTalkContext()); } } catch { MessageBox.Show("Make sure input is correct"); } }
将继承类库(ProTom、ProLuna)编译生成dll放置在Plug文件夹,Config.txt配置继承类的type
运行即可。
Plug文件夹截图:
所有代码均已压缩上传点击打开链接