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

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

  这里假定我们要开发一个记事本,选择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:

     这时加入了改变颜色的功能:

  由此可知,利用反射和接口,我们可以自定义插件实现不同的扩展功能,让我们的主软件项目更为强大!

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

在.NET中使用反射实现简易插件机制的更多相关文章

  1. 【转】.Net中通过反射技术的应用----插件程序的开发入门

    转自:http://www.cnblogs.com/winloa/archive/2012/03/25/2416355.html .Net中通过反射技术的应用----插件程序的开发入门 再开始之前,先 ...

  2. Spring 中的反射与反射的原理

    作者:DeppWang.原文地址 在造轮子:实现一个简易的 Spring IoC 容器一文中提到 Spring 在创建 Bean 实例和依赖注入时使用了反射,本文来具体分析一下 Spring 中的反射 ...

  3. 详解C#中的反射

    反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况.这是如何做到的呢?B超是B ...

  4. python中的反射

    在绝大多数语言中,都有反射机制的存在.从作用上来讲,反射是为了增加程序的动态描述能力.通俗一些,就是可以让用户参与代码执行的决定权.在程序编写的时候,我们会写很多类,类中又有自己的函数,对象等等.这些 ...

  5. .net中的反射(转载)

    原文地址:http://www.cnblogs.com/Stephenchao/p/4481995.html 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的 ...

  6. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  7. Java中的反射和注解

    前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...

  8. 分享20款移动开发中很有用的 jQuery 插件

    今天,很显然每个网站都需要有一个移动优化的界面以提高移动用户的使用体验.在开发任何移动项目时,要尽可能保持每一种资源尺寸都尽可能的小,以给最终用户提供一个好的体验是非常重要的.在这篇文章中我们已经编制 ...

  9. .Net 中的反射(序章) - Part.1

    引言 反射是.Net提供给我们的一件强力武器,尽管大多数情况下我们不常用到反射,尽管我们可能也不需要精通它,但对反射的使用作以初步了解在日后的开发中或许会有所帮助. 反射是一个庞大的话题,牵扯到的知识 ...

随机推荐

  1. 继承映射关系 TPH、TPT、TPC<EntityFramework6.0>

    每个类型一张表[TPT] 声明方式 public class Business { [Key] public int BusinessId { get; protected set; } public ...

  2. Etw EventSourceProvider_EventsProducer.cs OopConsoleTraceEventListenerMonitor_TraceControllerEventsConsumer.cs

    // EventSourceProvider_EventsProducer.cs /* /r:"D:\Microshaoft.Nuget.Packages\Microsoft.Diagnos ...

  3. WebGL入门教程(三)-webgl动画

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL动画有移动.旋转和缩放,我们将移动.旋转和缩放图形,然后将其绘制到屏幕上,称为变换(tr ...

  4. c语言结构体

    [C语言]21-结构体 本文目录 一.什么是结构体 二.结构体的定义 三.结构体变量的定义 四.结构体的注意点 五.结构体的初始化 六.结构体的使用 七.结构体数组 八.结构体作为函数参数 九.指向结 ...

  5. 转载:安装ie driver和chrome driver

    很多同学在使用webdriver的时候总是忘了安装ie driver和chrome driver, 因此在这里简单介绍一下这2个driver的安装方式. IE driver 在新版本的webdrive ...

  6. Hadoop 学习资料集锦

    Hadoop 资料 虾皮系列教程. Sqoop 资料 官方安装文档. 浪迹天涯博客. 瀚海星空博客. ……

  7. HTC辟谣: HTC Vive2不会在CES 2017上公布

    HTC官方:第二代Vive不会在CES 2017上发布.曾有消息称HTC Vive的下一代--Vive 2将在CES 2017上展出能成为首个4K头显以及无线头显.但日前HTC官方给于否认,此消息不实 ...

  8. PC端一些非经典兼容性问题小札

    IE10默认在input框中输入内容后会显示一个‘X’按钮,方便删除输入的所有内容. 在password输入框显示一个眼睛的按钮,去掉叉叉和眼睛的方法如下: ::-ms-clear { display ...

  9. C# winform安装部署(转载)

    c# winform 程序打包部署 核心总结: 1.建议在完成的要打包的项目外,另建解决方案建立安装部署项目(而不是在同一个解决方案内新建),在解决方案上右击-〉添加-〉现有项目-〉选择你要打包的项目 ...

  10. Python之路第一课Day11--随堂笔记(异步IO\数据库\队列\缓存之二)

    一.RabbitMQ队列 1.安装: a.官网: 安装 http://www.rabbitmq.com/install-standalone-mac.html b.安装python rabbitMQ ...