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

/// <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. 【转】Oracle回收站(recyclebin)

    我们都比较熟悉windows中的回收站,文件删除后放到回收站里还可以再复原.Oracle回收站的原理完全一样,只是实现的细节方面有些差异.另外回收站中只能回收表和相关的对象包括索引.约束.触发器.嵌套 ...

  2. mysql -- 优化之ICP(index condition pushdown)

    一.为了方法说明ICP是什么.假设有如下的表和查询: create table person( id int unsigned auto_increment primary key, home_add ...

  3. zookeeper 启动脚本

    #!/bin/bash export JAVA_HOME=/usr/java/latest export JRE_HOME=/usr/java/latest/jre zoo=/data/package ...

  4. spring(四) 手动整合web项目(SSH)

    清楚了spring的IOC 和 AOP,最后一篇就来整合SSH框架把,记录下来,以后应该会用的到. --WH 一.web项目中如何使用spring? 当tomcat启动时,就应该加载spring的配置 ...

  5. 【Unity】2.6 游戏视图(Game)

    分类:Unity.C#.VS2015 创建日期:2016-03-29 一.简介 游戏视图 (Game View) 从游戏的相机 ((Camera(s)) 中呈现,代表所发布游戏的最终版.你将需要一台或 ...

  6. android 学习视频汇总

    1.java基础知识 http://www.eoeandroid.com/thread-333511-1-1.html 网易公开课-抽象编程:http://open.163.com/special/o ...

  7. Android使用Custom debug keystore

    有时候须要用到第三方API的时候,须要一个key store 的SH1值,比如使用百度地图API,假设是协同开发,就须要全部Eclipse使用同一keystore. 例如以下图所看到的: 这里须要注意 ...

  8. confluence数据库的配置文件

    mysql> select u.id,u.user_name,u.active from cwd_user u join cwd_membership m on u.id=m.child_use ...

  9. 菜鸟学SSH(十)——Hibernate核心接口

    在使用Hibernate的时候,我们通常都会用的Configuration.SessionFactory.Session.Transaction.Query和Criteria等接口.通过这些接口可以, ...

  10. mysql protocol

    http://hutaow.com/blog/2013/11/06/mysql-protocol-analysis/ https://dev.mysql.com/doc/internals/en/cl ...