本篇是学习反射的一个应用小场景而做的学习笔记,主要是一个小的总结,并对各个步骤的记录,以便将来回顾。

一、基础框架-敏捷基础版本

  这里假定我们要开发一个记事本,选择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的更多相关文章

  1. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  2. 基础拾遗------redis详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  3. 基础拾遗------webservice详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  4. 基础拾遗-----mongoDB操作

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  5. 基础拾遗----RabbitMQ(含封装类库源码)

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  6. 基础拾遗----RabbitMQ

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  7. Java基础拾遗(二)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76358523冷血之心的博客) 马上就要秋招了,新的一轮笔试面试马上 ...

  8. Java基础拾遗(一)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76358391冷血之心的博客) 马上就要秋招了,新的一轮笔试面试马上 ...

  9. C#基础知识回顾-- 反射(3)

    C#基础知识回顾-- 反射(3)   获取Type对象的构造函数: 前一篇因为篇幅问题因为篇幅太短被移除首页,反射这一块还有一篇“怎样在程序集中使用反射”, 其他没有什么可以写的了,前两篇主要是铺垫, ...

  10. C#基础知识回顾-- 反射(1)

    C#基础知识回顾-- 反射(1)   反射(reflection)是一种允许用户获得类型信息的C#特性.术语“反射”源自于它的工作方式: Type对象映射它所代表的底层对象.对Type对象进行查询可以 ...

随机推荐

  1. QQ 国际版(International version) - 关闭弹出资讯

    1,打开QQ面板,点击左下角的 "企鹅"图标.选择 "Setting". 2,在弹出的 "Setting"面板中,选择 "Priv ...

  2. iOS中你必须了解的多线程

    多线程概念详解 什么是进程? 简单的说进程就是我们电脑上运行的一个个应用程序,每一个程序就是一个进程,并且每个进程之间是独立的,每个进程运行在其专用受保护的内存空间内(window系统可以通过任务管理 ...

  3. n行m列的网格中含有的矩形数

    给你一个高为n ,宽为m列的网格,计算出这个网格中有多少个矩形 公式:[ n(n+1)*m(m+1)]/4 直接想问题比较复杂,可以先考虑矩形的长,再考虑矩形的高,由对称性可知最后的结果中m和n对称 ...

  4. C++基于模板顺序表的实现(带排序)

    说明:代码是可以运行的,但是发表在博客上后复制到编译器里面报N多错误,找了半天原因是网页里面生成了一些空白字符,这些字符编译器无法识别. 因此使用了2种插入格式插入代码. 第二个带注释解释的代码不可复 ...

  5. instanceof操作符判断对象类型

    instanceof 的语法格式如下: myobject instanceof ExampleClass myobject:某类的对象引用 ExampleClass:某个类 class Quadran ...

  6. 在预装win8的电脑上换win7系统讲解

    现在买电脑,如果电脑预装的系统是win8系统,那么这个电脑的默认启动模式应该就是UEFI模式,现在UEFI模式正在逐渐取代传统模式.UEFI启动需要一个独立的分区,它将系统启动文件和操作系统本身隔离, ...

  7. QT creator中使用opencv

    最近要用到opencv做图像方面的东西,网上很多是用VS加opencv,但自己对VS不怎么喜欢,想用QT Creator.在网上搜索了很多资料,终于花了一天的时间,在QT Creator上能使用ope ...

  8. activity,view,window,windowmanager代码阅读总结及相互关系

    ActivityThread类:performLaunchActivity函数: activity.attach(appContext, this, getInstrumentation(), r.t ...

  9. 使用QtScript库解析Json数组例子

    本文转载自:http://blog.sina.com.cn/s/blog_671732440100uwxh.html 使用qtscipt库解析json数组首先在工程文件中加 QT        += ...

  10. cf445B DZY Loves Chemistry

    B. DZY Loves Chemistry time limit per test 1 second memory limit per test 256 megabytes input standa ...