c#判断事件是否已被注册

近日做了一个针对项目的树形控件,对外提供选中节点更改事件,执行该事件方法的代码如下:

 

 

msdn上有完整的示例代码,具体可参见:如何:在类中实现事件

 

另看到有博文[C#如何取得事件注册的方法],其实二者的思路是一样的,只是目的有所不同而已。

C#中,判断事件是否已经绑定有以下几种方法: ### 简单判断事件是否null 在发出事件的方法中,通常会先判断事件是否null 来确定是否事件处理方法绑定。示例如下: ```csharp // 发出事件 public void OnDinnerComing( string msg ) { // 判断是否绑定了事件处理方法 if( null != DinnerEvent ) { // 触发事件 DinnerEvent( msg ); } } ``` 这里通过判断 `DinnerEvent` 是否为 `null` 来确定是否事件处理方法绑定到该事件上 [^1]。 ### 通过反射获取事件处理程序列表判断 可以使用反射获取对象的事件处理程序列表,然后检查是否有绑定的事件处理程序。 #### 方法一 ```csharp // 是否已经绑定了事件 private bool IsBindEvent(Type type, Control con, string eventName) { bool isBind = false; PropertyInfo pi = type.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); // 获取type类定义的所有事件的信息 EventHandlerList ehl = (EventHandlerList)pi.GetValue(con, null); // 获取con对象的事件处理程序列表 FieldInfo fieldInfo = (typeof(Control)).GetField("EventText", BindingFlags.Static | BindingFlags.NonPublic); // 获取Control类Click事件的字段信息 Delegate d = ehl[fieldInfo.GetValue(null)]; if (d == null) { return isBind; } foreach (Delegate del in d.GetInvocationList()) { if (del.Method.Name == eventName) { isBind = true; break; } } return isBind; } ``` 此方法通过反射获取控件的事件处理程序列表,然后检查指定名称的事件处理程序是否存在 [^2]。 #### 方法二 ```csharp public static class ComponentHelper<T> where T : Control { public static bool HaveEventHandler(T control, string eventName, string methodName) { // 获取Button类定义的所有事件的信息 PropertyInfo pi = (typeof(T)).GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); // 获取Button对象btn的事件处理程序列表 EventHandlerList ehl = (EventHandlerList)pi.GetValue(control, null); // 获取Control类Click事件的字段信息 FieldInfo fieldInfo = (typeof(Control)).GetField($"Event{eventName}", BindingFlags.Static | BindingFlags.NonPublic); // 用获取的Click事件的字段信息,去匹配btn对象的事件处理程序列表,获取btn对象Click事件的委托对象 // 事件使用委托定义的,C#中的委托时多播委托,可以绑定多个事件处理程序,当事件发生时,这些事件处理程序被依次执行 // 因此Delegate对象,有一个GetInvocationList方法,用来获取这个委托已经绑定的所有事件处理程序 Delegate d = ehl[fieldInfo.GetValue(null)]; foreach (Delegate del in d.GetInvocationList()) { // 判断一下某个事件处理程序是否已经被绑定到Click事件上 if (del.Method.Name == methodName) { return true; } } return false; } } ``` 该方法是一个泛型静态方法,通过反射获取指定控件的事件处理程序列表,并检查指定名称的事件处理程序是否绑定到指定事件上 [^3]。 ### 通过获取事件注册的方法名判断 ```csharp /// <summary> /// 查找控件的对应的事件注册的方法名 /// </summary> /// <param name="control">控件</param> /// <param name="eventName">事件</param> /// <returns>返回事件注册的方法名,若未找到则返回null</returns> private static string GetBindingMethod(Control control, string eventName) { // EventInfo info = control.GetType().GetEvent(eventName); PropertyInfo propertyInfo = control.GetType().GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); if (propertyInfo == null) { return null; } EventHandlerList eventList = (EventHandlerList)propertyInfo.GetValue(control, null); FieldInfo fieldInfo = typeof(Control).GetField("Event" + eventName, BindingFlags.Static | BindingFlags.NonPublic); if (fieldInfo == null) { return null; } Delegate delegateInfo = eventList[fieldInfo.GetValue(control)]; if (delegateInfo == null) { return null; } Delegate[] delegateList = delegateInfo.GetInvocationList(); return delegateList[delegateList.Length - 1].Method.Name; } ``` 此方法通过反射获取控件的事件处理程序列表,然后尝试获取指定事件最后一个注册的方法名,如果返回 `null` 则表示该事件未绑定方法 [^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值