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

Check if a method is already registered to an event

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

That Whosebug question 提供了 2 种解决方案:

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

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;
    }
}
  1. 为了调用 CheckOnSomething,我需要将委托传递给 CatchSomething。我是否必须为此定义一个新委托,或者是否已经有我可以使用的东西?
  2. 如果我定义一个新委托,委托平等会起作用吗?文档说它检查委托类型,但由于我直接传递了方法,所以不是动态创建的新委托类型,这会使相等性始终 return false ?

In order to call CheckOnSomething, I need to pass a delegate to CatchSomething. Do I have to define a new delegate for that, or is there already something I can use ?

你可以直接通过CatchSomething:

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

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

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

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

If I define a new delegate, will the delegate equality work ? The documentation says it checks for the delegate type, but since I pass the method directly, isn't a new delegate type created on the fly, which would make the equality always return false ?

传递该方法会创建一个新委托 实例 而不是新委托 类型;委托 type 将始终是 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