.NET基础拾遗(5)反射2
本篇是学习反射的一个应用小场景而做的学习笔记,主要是一个小的总结,并对各个步骤的记录,以便将来回顾。
一、基础框架-敏捷基础版本
这里假定我们要开发一个记事本,选择Windows Form技术开发,界面如下图所示:
该记事本只提供了一个TextBox供输入,以及保存到指定文件。其他功能均没有实现,假定我们先把这个版本做出来,后续功能通过插件形式一步一步完成。
但是,为了能够使用插件,我们的主项目还得经过一些改造:
(1)加载时需要从插件目录中获取插件
public FormMain()
{
InitializeComponent();
// 加载插件
LoadPlugins();
} private void LoadPlugins()
{
// 1.加载plugins目录下的所有的dll文件
string plugins = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "plugins");
// 1.1 搜索plugins目录下的所有的dll文件
string[] dlls = Directory.GetFiles(plugins, "*.dll");
// 2.循环将每个dll文件都加载起来
foreach (string dllPath in dlls)
{
// 2.1 动态加载当前循环的dll文件
Assembly assembly = Assembly.LoadFile(dllPath);
// 2.2 获取当前dll中的所有的public类型
Type[] types = assembly.GetExportedTypes();
// 2.3 获取IEditor接口的Type
Type typeIEditor = typeof(IEditor); for (int i = ; i < types.Length; i++)
{
// 2.4 验证当前的类型即实现了IEditor接口并且该类型还可以被实例化
if (typeIEditor.IsAssignableFrom(types[i]) && !types[i].IsAbstract)
{
IEditor editor = (IEditor)Activator.CreateInstance(types[i]);
// 2.5 向菜单栏中动态添加一个菜单项
ToolStripItem toolItem = toolstripEditMenu.DropDownItems.Add(editor.PluginName);
// 2.6 为刚刚增加的菜单项注册一个单击事件
toolItem.Click += new EventHandler(toolItem_Click);
toolItem.Tag = editor;
}
}
}
}
(2)为插件设置通用的Click事件
private void toolItem_Click(object sender, EventArgs e)
{
ToolStripItem item = sender as ToolStripItem;
if (item != null)
{
if (item.Tag != null)
{
IEditor editor = item.Tag as IEditor;
if (editor != null)
{
// 运行该插件
editor.Execute(this.txtContent);
}
}
}
这里约定所有插件都实现了IEditor接口,并且所有插件的功能都在Execute方法中被实现。
二、约定接口-可扩展的基础
不难发现,如果我们直接使用反射调用dll,即使我们找到了dll文件,也没法知道里面的函数叫什么名字,即使可以枚举出来,也没法智能的调用里面的函数,实现我们预期的功能扩展。于是我们犯难了,我们已经写好的程序哪能预料以后会调用哪些dll的哪些函数呢?
其实这个并不复杂,我们可以利用接口技术实现这样一种功能。所谓接口,就是一份协议,当大家编写dll时都遵守这样一个协议,那么我们写的dll就可以方便的被exe调用。
对于这个小demo而言,我们设计一个IEditor接口如下:
public interface IEditor
{
string PluginName
{
get;
} void Execute(TextBox txtbox);
}
其中,PluginName是插件的名称,用于菜单显示。Execute方法则接收记事本的TextBox控件,用于实现具体的功能。
三、实现插件-可升级的功能
(1)插件1:将文本全部转为大写
新建一个类库项目,设计一个实现IEditor接口的类:
public class ChangeFontStyle : IEditor
{
public string PluginName
{
get
{
return "转为大写";
}
} public void Execute(TextBox txtbox)
{
if (!string.IsNullOrEmpty(txtbox.Text))
{
txtbox.Text = txtbox.Text.ToUpper();
}
else
{
MessageBox.Show("请先输入文字!");
}
}
(2)插件2:将文本全部变为红色
新建一个类库项目,设计一个实现IEditor接口的类:
public class ChangeFontColor : IEditor
{
public string PluginName
{
get
{
return "改变颜色";
}
} public void Execute(TextBox txtbox)
{
if (!string.IsNullOrEmpty(txtbox.Text))
{
txtbox.ForeColor = System.Drawing.Color.Red;
}
else
{
MessageBox.Show("请先输入文字!");
}
}
}
四、拥抱变化-简单的测试
(1)没有任何插件的记事本程序
Plugins 插件目录下一个dll也木有:
因此我们的记事本只有最基本的操作:
(2)加入插件1(转换大写)的记事本程序
Plugins 插件目录有一个dll:
这时加入了转换大写的功能:
(3)加入插件2(改变颜色)的记事本程序
Plugins 插件目录有两个dll:
这时加入了改变颜色的功能:
由此可知,利用反射和接口,我们可以自定义插件实现不同的扩展功能,让我们的主软件项目更为强大!
.NET基础拾遗(5)反射2的更多相关文章
- .NET基础拾遗(4)委托、事件、反射与特性
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- 基础拾遗------redis详解
基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...
- 基础拾遗------webservice详解
基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...
- 基础拾遗-----mongoDB操作
基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...
- 基础拾遗----RabbitMQ(含封装类库源码)
基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...
- 基础拾遗----RabbitMQ
基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...
- Java基础拾遗(二)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76358523冷血之心的博客) 马上就要秋招了,新的一轮笔试面试马上 ...
- Java基础拾遗(一)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76358391冷血之心的博客) 马上就要秋招了,新的一轮笔试面试马上 ...
- C#基础知识回顾-- 反射(3)
C#基础知识回顾-- 反射(3) 获取Type对象的构造函数: 前一篇因为篇幅问题因为篇幅太短被移除首页,反射这一块还有一篇“怎样在程序集中使用反射”, 其他没有什么可以写的了,前两篇主要是铺垫, ...
- C#基础知识回顾-- 反射(1)
C#基础知识回顾-- 反射(1) 反射(reflection)是一种允许用户获得类型信息的C#特性.术语“反射”源自于它的工作方式: Type对象映射它所代表的底层对象.对Type对象进行查询可以 ...
随机推荐
- 解析c语言背后的汇编代码
源码 很简单的c语言代码,作用是交换两个数: #include <stdio.h> void swap(int * a, int * b) { *a = *a + *b - (*b = * ...
- jQuery Scroll div滚动条样式更改
<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script> ...
- 验证码 Demo
//设置响应头 response.setCharacterEncoding("image/jpeg"); int width=160; int height=40; Buffere ...
- ajax初学
//参数说明url:请求文件地址//fnSucc:请求成功执行的函数,请求成功的条件为readyState状态码为4:且status状态码为200,status状态为浏览器请求返回的状态码//在fnS ...
- jQuery对下拉框、单选框、多选框的处理
下拉框: //得到下拉菜单的选中项的文本(注意中间有空格) var cc1 = $(".formc select[@name='country'] option[@selected]&quo ...
- 关于lambda表达式树
总而言之: 就是在表达式中没有花括号. IEnumerable<Rect> rectlist3 = rectlist.Select(rect =>newRect(rect.X + 2 ...
- Smartcard CA智能卡之调试
Integrated Circuit Card 集成电路卡,也叫CA卡或智能卡,将一个微电子芯片嵌入符合ISO 7816标准的卡基内,做成卡片形式,也是一个嵌入式小系统.由CPU,ROM,RAM及E ...
- 自定义DTD(myeclipser的XML提示功能)
了解DTD定义详见:http://www.w3school.com.cn/dtd/dtd_elements.asp PS:文本只是简单的介绍,启到抛砖引玉的作用. 1.创建DTD文件 <?xml ...
- ZOJ2317-Nice Patterns Strike Back:矩阵快速幂,高精度
Nice Patterns Strike Back Time Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Java/ ...
- 面试题32.从1到n整数中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从 1到12这些整数中包含1的数字中1,10,11和12,1一共出现了5次 本题可以直接变量1到n的n个数然后分别计 ...