检查方法是否已注册到事件

问题描述

我正在尝试正确检查对象的事件是否已设置为特定方法

That stackoverflow question 提供了两种解决方案:

我有几个与第二个解决方案相关的问题。 让我们假设以下代码

type T0 = {a:number,b:number}
type T1 = {a:number,c:number,d:number}
type Test=[T0]|[T1]
const t1:Test=[{a:1,b:1,}]  
const t2:Test=[{a:1,c:1,d:1}]  
const t3:Test=[{a:1,c:1}] // fails as desired
  1. 为了调用 public static class Util { public static bool IsRegistered<T>(this EventHandler<T> handler,Delegate prospectiveHandler) => handler != null && handler.GetInvocationList().Any(existingHandler => existingHandler == prospectiveHandler)); } public class Object1 { public event EventHandler<string> OnSomething; public bool CheckOnSomething(Delegate handler) => this.OnSomething.IsRegistered(handler); } public class Object2 { private Object1 o; public Object2(Object1 o1) { this.o = o1; } public void CatchSomething(object sender,string something) { // ... } public void HookToSomething() { if (!o.CheckOnSomething( ??? )) o.OnSomething += this.CatchSomething; } } ,我需要将委托传递给 CheckOnSomething。我是否必须为此定义一个新的委托,或者是否已经有我可以使用的东西?
  2. 如果我定义了一个新的委托,委托平等是否有效?文档说它会检查委托类型,但由于我直接传递了该方法,因此不是动态创建的新委托类型,这会使等式始终返回 CatchSomething 吗?

解决方法

为了调用 CheckOnSomething,我需要将委托传递给 CatchSomething。我必须为此定义一个新的委托,还是已经有可以使用的东西?

您可以直接传递 CatchSomething

if (!o.CheckOnSomething(CatchSomething))
    o.OnSomething += CatchSomething;

但是您需要更新 CheckOnSomething 以接受特定的委托类型,以便可以转换 CatchSomething

public bool CheckOnSomething(Action<object,string> handler)
    => this.OnSomething.IsRegistered(handler);

这也提高了类型安全性,因为现在只有具有正确签名的委托才能被传递。

如果我定义一个新的委托,委托平等是否有效?文档说它会检查委托类型,但是由于我直接传递了该方法,所以不是动态创建的新委托类型,这会使等式始终返回 false 吗?

传递该方法会创建一个新的委托实例,而不是一个新的委托类型;委托类型将始终为Action<object,string>

然而,delegate equality 依赖于目标和类型,因此传递 CatchSomething 只有在形成同一个实例时才会被认为是相等的。

例如:

var obj1 = new Object1();
var instance1 = new Object2(obj1);

// Creates a delegate instance:
Action<object,string> catchSomething = instance1.CatchSomething;

catchSomething == instance1.CatchSomething; // true

var instance2 = new Object2(obj1);

catchSomething == instance2.CatchSomething; // false