控件的事件清除,除了-=,就只能依靠反射来执行了。

/// <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# 利用反射清除事件的更多相关文章

  1. 利用反射绑定事件处理程序(C#)

    利用反射绑定事件处理程序(C#) 传统的写法:强类型的情况下 using System;using System.Collections.Generic;using System.Text; usin ...

  2. C# 调用一个按钮的Click事件(利用反射)

    最基本的调用方法 (1)button1.PerformClick();(2)button1_Click(null,null);(3)button_Click(null,new EventArgs()) ...

  3. 利用反射--调用一个按钮的Click事件

    最基本的调用方法 (1)button1.PerformClick();(2)button1_Click(null,null);(3)button_Click(null,new EventArgs()) ...

  4. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  5. C#回顾 - 8.利用反射动态创建对象

    拿微信消息返回的示例数据实验 var data = "<xml><ToUserName><![CDATA[toUser]]></ToUserName ...

  6. Python基础篇【第3篇】: Python异常处理、反射、动态导入、利用反射的web框架

    异常处理 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当P ...

  7. c#反射机制学习和利用反射获取类型信息

    反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获得.NET中每一个类型(包括类.结构.委托.接口和枚举等)的成员,包括方法.属性.事件,以及构造函数等.还可以获得每个成员的 ...

  8. 利用反射修改final数据域

    当final修饰一个数据域时,意义是声明该数据域是最终的,不可修改的.常见的使用场景就是eclipse自动生成的serialVersionUID一般都是final的. 另外还可以构造线程安全(thre ...

  9. 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)

    试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...

随机推荐

  1. 温故而知新:柯里化 与 bind() 的认知

    什么是柯里化?科里化是把一个多参数函数转化为一个嵌套的一元函数的过程.(简单的说就是将函数的参数,变为多次入参) const curry = (fn, ...args) => fn.length ...

  2. 转 部署Zipkin分布式性能追踪日志系统的操作记录

    2017年02月27日 11:01:29 https://blog.csdn.net/konglongaa/article/details/58016398 阅读数:7631 Zipkin是Twitt ...

  3. django -- verbose_name的对数据库层面的影响

    一.没有verbose_name时model的定义: from django.db import models # Create your models here. class Question(mo ...

  4. 如何使用Git 下载GitHub的东西

    1. 先安装git 2. 注册一个github账号 3. 新建一个项目 3. 打开git 运行以下命令: cd /d/workspace (切换目录到 d盘的workspace) git init ( ...

  5. grafana 的面板设置

    1.工作中我们会计算连个字段的四则运算

  6. [jk]服务器远控卡及kvm切换器

    远控卡的需求 经常我们有这么一个需求,那就是某一台器服务器突然宕机,不能启动,而机房却在外地.解决这个问题的方法有两种,一是联系机房人员,二是通过idrac卡远程连接.我们必须根据事情的轻重缓急,来选 ...

  7. sql中计算某天是全年的第几周及取得某天的所在周的周一的日期的函数

    --取得某天的所在周的周一的函数 CREATE FUNCTION getMondayBtDate(@date datetime) RETURNS date AS begin DECLARE @week ...

  8. 淘宝分布式数据层TDDL

    剖析淘宝 TDDL ( TAOBAO DISTRIBUTE DATA LAYER ) 注:原文:http://gao-xianglong.iteye.com/blog/1973591   前言 在开始 ...

  9. hdu 1879 继续通畅工程(最小生成树)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1879 /************************************************* ...

  10. zabbix 实现对服务器的负载监控

    # grep Include /etc/zabbix/zabbix_agentd.conf ### Option: Include # Include= Include=/etc/zabbix/zab ...