.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对象进行查询可以 ...
随机推荐
- R语言编程艺术# 矩阵(matrix)和数组(array)
矩阵(matrix)是一种特殊的向量,包含两个附加的属性:行数和列数.所以矩阵也是和向量一样,有模式(数据类型)的概念.(但反过来,向量却不能看作是只有一列或一行的矩阵. 数组(array)是R里更一 ...
- C库专题(Day1)
<assert.h> C库宏-assert() 定义:#define assert(ignore) ((void)0) void assert(int experession); ex ...
- vs2013+EF6+Mysql
1.首先需要在整个项目中添加一个Model类库,在类库中引用EF 我需要在该项目下添加EF的MYSQL对象实体 首先需要引入几个相关引用,我通过NuGet来添加,如下图 接下来我需要通过ADO.NET ...
- 如何改写WebApi部分默认规则
为什么要改 最近公司在推广SOA框架,第一次正经接触这种技术(之前也有但还是忽略掉吧),感觉挺好,就想自己也折腾一下,实现一个简单的SOA框架 用过mvc进行开发,印象之中WebApi和Mvc好像是一 ...
- Qt5.4静态编译方法
静态编译,就是编译器在编译可执行文件的时候,将可执行文件需要调用的对应动态链接库(.so或.lib)中的部分提取出来,链接到可执行文件中去,使可执行文件在运行的时候不依赖于动态链接库.这样就可以发布单 ...
- Heroku 部署时 time out 错误,对GFW无力吐槽!!!
整理自:http://ruby-china.org/topics/10813 部署到Heroku时输入 git push heroku master. 然后就开始漫长的等待了,最终报错: ssh: c ...
- win7下的iis配置
1.配置错误 说明:在处理向该请求提供服务所需的配置文件时出错.请检查下面的特定错误详细信息并适当地修改配置文件. 分析器错误消息:无法识别的属性“targetFramework”.请注意属性名称区分 ...
- Java学习笔记--集合元素的比较Comparable,Comparator
原文见: http://www.cnblogs.com/sunflower627/p/3158042.html 1. Comparator 和 Comparable 相同的地方 他们都是java的一个 ...
- 性能测试 - some
1.日常业务中测试过的最大并发数,其QPS为多少? 答: 从服务端开发处得知线上某台机器单接口访问量为63万 因该接口为视频类访问接口,大多数接口集中于晚间时段.可计算QPS = 63万/8/3600 ...
- iOS中设置导航栏标题的字体颜色和大小
iOS中设置导航栏标题的字体颜色和大小,有需要的朋友可以参考下. 在平时开发项目的时候,难免会遇到修改导航栏字体大小和颜色的需求,一般使用自定义视图的方法,其实还存在一种方法. 方法一:(自定义视图的 ...