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多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...
随机推荐
- Vue style 深度作用选择器 >>> 与 /deep/(sass/less)
传送门:https://vue-loader-v14.vuejs.org/zh-cn/features/scoped-css.html 你很可能会遇到的问题 vue组件编译后,会将 template ...
- es5 温故而知新 创建私有成员、私有变量、特权变量的方法
其实js是不支持私有变量的.哪怕到es6的class语法.虽然有许多变相的方式.但非常冗余而不推崇. 这里介绍的实际上也不是class语法,而是普通的函数,并且利用IIFE(闭包)的方式来实现私有. ...
- nginx 读取文件 permission denied
nginx 是在root用户下安装的,静态网页的目录/var/www/html/ 目录下的内容所有者也是root 用户,按照 nginx配置文件中location说明 配置静态文件访问地址. 使用网址 ...
- ubuntu 14.04安装mysql数据库
1. apt-get install mysql-server mysql-client 输入root的密码: 确认root的密码: 2. 连接测试是否成功:mysql –hlocalhost –ur ...
- 两table水平滚动条级联滚动(同步滚动)。 table1放标题,table2放内容。
//table1=head和table2=body水平滚动条级联滚动 $(document).ready(function () { $("#bodyPanel").scroll( ...
- win764bit系统plsqldeveloper11连接oracle11g64bit配置方法
win764bit系统plsqldeveloper11连接oracle11g64bit配置方法: 原因:plsqldeveloper都是32位的没有64位的程序 准备工作: 1,先要下载instant ...
- Android 计算文件 MD5 遇到的问题
版本下载,做 MD5 校验,使用的 MD5 算法出现了异常,当出现以 0 开头的 MD5的时候,会把 0 给忽略掉,造成 MD5 只有 31 位,造成校验失败. 转:http://blog.csdn. ...
- MYSQL拒绝访问:not allowed to connect解决方法
分享下MYSQL拒绝访问报错not allowed to connect的解决方法. 可以在其它任何的主机上以root身份登录 mysql报如下错误,截取部分, message from server ...
- LeetCode 326 Power of Three(3的幂)(递归、Log函数)
翻译 给定一个整型数,写一个函数决定它是否是3的幂(翻译可能不太合适-- 跟进: 你能否够不用不论什么循环或递归来完毕. 原文 Given an integer, write a function t ...
- Android数据库高手秘籍(零)——前言
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/38083103 在我刚開始接触Android的时候甚至都不敢相信.Android系统 ...