VB.NET中如何在类内判断另一类是否绑定了对应事件的处理程序
结论
你期望的DoSomething.WasHandled这种直接判断语法在VB.NET中没有原生提供,但可以通过自定义事件管理委托列表或反射的方式实现需求,无需为事件添加额外参数。
推荐实现方案(自定义事件)
通过VB.NET的Custom Event语法手动管理事件的订阅委托列表,直接获取订阅者信息判断是否存在类B的处理程序:
Public Class A ' 存储事件所有订阅者的委托字段 Private DoSomethingHandler As Action ' 自定义事件的订阅、退订、触发逻辑 Public Custom Event DoSomething As Action AddHandler(value As Action) DoSomethingHandler = [Delegate].Combine(DoSomethingHandler, value) End AddHandler RemoveHandler(value As Action) DoSomethingHandler = [Delegate].Remove(DoSomethingHandler, value) End RemoveHandler RaiseEvent() DoSomethingHandler?.Invoke() End RaiseEvent End Event Public Sub RaiseDoSomething() RaiseEvent DoSomething() ' 判断是否存在类B实例订阅的处理程序 Dim hasBHandler = DoSomethingHandler? .GetInvocationList()? .Any(Function(d) d.Target?.GetType() = GetType(B)) If hasBHandler = True Then DoSomethingElse() End If End Sub Private Sub DoSomethingElse() ' 存在类B处理程序时执行的逻辑 End Sub End Class Public Class B Public WithEvents SomeA As New A Private Sub HandleDoSomething() Handles SomeA.DoSomething ' 事件处理逻辑 End Sub End Class
方案说明
Custom Event语法允许你完全掌控事件的委托列表存储,不需要依赖编译器隐式生成的内部字段- 调用委托的
GetInvocationList()方法可以拿到所有订阅该事件的委托实例,每个委托的Target属性就是处理程序所属的类实例 - 只需要判断
Target的类型是否为B,就能确认类B是否存在对应事件的处理程序,完全不需要修改事件参数
替代实现方案(反射)
如果你不想修改原有事件的定义,可以通过反射读取编译器为隐式事件生成的后台委托字段实现相同判断:
Public Class A Public Event DoSomething() Public Sub RaiseDoSomething() RaiseEvent DoSomething() ' 反射读取VB编译器为DoSomething事件隐式生成的委托字段 Dim eventField = GetType(A).GetField("DoSomethingEvent", System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.NonPublic) Dim handler = CType(eventField.GetValue(Me), Action) Dim hasBHandler = handler? .GetInvocationList()? .Any(Function(d) d.Target?.GetType() = GetType(B)) If hasBHandler = True Then DoSomethingElse() End If End Sub Private Sub DoSomethingElse() ' 存在类B处理程序时执行的逻辑 End Sub End Class
方案说明
- VB编译器默认会为隐式声明的事件生成命名规则为
[事件名]Event的私有委托字段,反射读取该字段即可拿到所有订阅者 - 该方案不需要修改原有事件定义,但依赖编译器的内部命名规则,兼容性弱于自定义事件方案
扩展说明
如果你的判断需求是特定某个B类实例是否订阅了事件,而非所有B类型的实例,只需要将判断逻辑修改为比较d.Target是否等于目标B类实例即可。
内容的提问来源于stack exchange,提问作者FaultyOverflow
相关产品推荐
相关产品推荐

