c# 利用反射清除事件
控件的事件清除,除了-=,就只能依靠反射来执行了。
/// <summary>
/// 清除一个对象的某个事件所挂钩的delegate
/// </summary>
/// <param name="ctrl">控件对象</param>
/// <param name="eventName">事件名称,默认的</param>
public static void ClearEvents(this object ctrl, string eventName = "_EventAll")
{
if (ctrl == null) return;
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Static;
EventInfo[] events = ctrl.GetType().GetEvents(bindingFlags);
if (events == null || events.Length < ) return; for (int i = ; i < events.Length; i++)
{
try
{
EventInfo ei = events[i];
//只删除指定的方法,默认是_EventAll,前面加_是为了和系统的区分,防以后雷同
if (eventName != "_EventAll" && ei.Name != eventName) continue; /********************************************************
* class的每个event都对应了一个同名(变了,前面加了Event前缀)的private的delegate类
* 型成员变量(这点可以用Reflector证实)。因为private成
* 员变量无法在基类中进行修改,所以为了能够拿到base
* class中声明的事件,要从EventInfo的DeclaringType来获取
* event对应的成员变量的FieldInfo并进行修改
********************************************************/
FieldInfo fi = ei.DeclaringType.GetField("Event" + ei.Name, bindingFlags);
if (fi != null)
{
// 将event对应的字段设置成null即可清除所有挂钩在该event上的delegate
fi.SetValue(ctrl, null);
}
}
catch { }
}
}
当前使用环境.net 4.0。参考了很多其他人的代码,有三个地方值得注意。
一个是eventName,GetField的时候在原来的Name前面加"Event"前缀。这个可能在不同的.net版本不一样,出现过三种:eventName,"Event"+eventName, "Event_" + controlType.Name + eventname.
第二个:BindingFlags。尽量用Public | NonPublic | Instance | IgnoreCase | Static。
第三:GetField的执行对象用EventInfo.DeclaringType,否则有可能继承的类获取不到数据。
补充一个测试。下面的代码中Button会执行三次-=然后+=,但是每次的对象都是重新new的。三次绑定后,点击button1时,只执行一次输出。
public Form1()
{
this.Load += (a, b) =>
{
new Thread(new ThreadStart(() =>
{
int i = ;
while (true)
{
if (button1.InvokeRequired) button1.Invoke(new Action(ReBindEvent));
else ReBindEvent();
Thread.Sleep();
i++;
if (i >= ) break;
}
})).Start();
};
} void ReBindEvent()
{
button1.Click -= GetClickHandle();
button1.Click += GetClickHandle();
} EventHandler GetClickHandle()
{
return new EventHandler((a, b) =>
{
Console.WriteLine(DateTime.Now + " 执行一次");
});
}
c# 利用反射清除事件的更多相关文章
- 利用反射绑定事件处理程序(C#)
利用反射绑定事件处理程序(C#) 传统的写法:强类型的情况下 using System;using System.Collections.Generic;using System.Text; usin ...
- C# 调用一个按钮的Click事件(利用反射)
最基本的调用方法 (1)button1.PerformClick();(2)button1_Click(null,null);(3)button_Click(null,new EventArgs()) ...
- 利用反射--调用一个按钮的Click事件
最基本的调用方法 (1)button1.PerformClick();(2)button1_Click(null,null);(3)button_Click(null,new EventArgs()) ...
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- C#回顾 - 8.利用反射动态创建对象
拿微信消息返回的示例数据实验 var data = "<xml><ToUserName><![CDATA[toUser]]></ToUserName ...
- Python基础篇【第3篇】: Python异常处理、反射、动态导入、利用反射的web框架
异常处理 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当P ...
- c#反射机制学习和利用反射获取类型信息
反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获得.NET中每一个类型(包括类.结构.委托.接口和枚举等)的成员,包括方法.属性.事件,以及构造函数等.还可以获得每个成员的 ...
- 利用反射修改final数据域
当final修饰一个数据域时,意义是声明该数据域是最终的,不可修改的.常见的使用场景就是eclipse自动生成的serialVersionUID一般都是final的. 另外还可以构造线程安全(thre ...
- 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)
试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...
随机推荐
- 8.翻译:EF基础系列----EF中实体的状态
原文链接:http://www.entityframeworktutorial.net/basics/entity-states.aspx 在实体的生命周期中,EF API维护着每一个实体的状态,对于 ...
- Batch to setup JAVA programming environment for Algorithm class from priston
Original web site: http://algs4.cs.princeton.edu/linux/ Part. I [username:~/] [username:~/] mkdir al ...
- IOS7 新特性
相关ios7新特性 帖子.挺全的.一定要看看哪 http://www.devdiv.com/iOS_iPhone-ios_ui_uikit_text_kit_-thread-203631-1-1.ht ...
- wget常见用法
1.很多软件官网会有安装脚本,并把脚本搞成raw模式,方便下载后直接运行的shell文件.比如docker wget -qO- get.docker.com | bash -q的含义是:--quiet ...
- cygwin下安装c语言开发环境
1.到官网cygwin.com下载安装程序. 2.添加清华的cygwin镜像:https://mirrors.tuna.tsinghua.edu.cn/cygwin/ 3.在安装:vim,git,gc ...
- Vivado神器之DocNav
Vivado2014安装完成以后会有2个文件出现在桌面上,具体如下图: 上一个是vivado的软件,是主要的工具,但是一定不要忽略下面一个DocNav,今天我要讲的就是这个工具,打开一个会看到这样一个 ...
- CCardSlip
该类已经把tableview封装好,可以把它当做一个精灵来用,这样做的好处是,当一个界面同时需要多个tableview的时候就可以很好的解决这个问题,而且模块也更清晰. //------------- ...
- tomcat最大并发连接数的修改方法
转载:http://blog.csdn.net/qysh123/article/details/11678903 这是个很简单的问题,但是搜了一圈,发现大家都写错了.所以这里总结一下: 几乎所有的中文 ...
- [开源项目-MyBean轻量级配置框架] 使用MyBean快速搭建分模块的应用程序(主页面的TAB)(DLL-MDI)
[概述] 抱歉由于上次开源比较匆忙,没有来的及做一个DEMO,里面也有些垃圾的文件没有及时清理.DEMO其实昨天晚上已经调通.相关说明文档今天晚上才说明好,欢迎大家继续关注和交流,和大家一起分享我10 ...
- 【Linux技术】linux之configure,pkg-config和PKG_CONFIG_PATH
linux之configure,pkg-config和PKG_CONFIG_PATH 1.初衷 1)前面在装gtk时冒出来一个pkg-config,当时虽然不大清楚它是个什么东西,不过大致了解了下它的 ...