检查方法是否已注册到事件
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;
}
}
- 为了调用
CheckOnSomething
,我需要将委托传递给 CatchSomething
。我是否必须为此定义一个新委托,或者是否已经有我可以使用的东西?
- 如果我定义一个新委托,委托平等会起作用吗?文档说它检查委托类型,但由于我直接传递了方法,所以不是动态创建的新委托类型,这会使相等性始终 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
我正在尝试正确检查对象的事件是否已设置为特定方法。
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;
}
}
- 为了调用
CheckOnSomething
,我需要将委托传递给CatchSomething
。我是否必须为此定义一个新委托,或者是否已经有我可以使用的东西? - 如果我定义一个新委托,委托平等会起作用吗?文档说它检查委托类型,但由于我直接传递了方法,所以不是动态创建的新委托类型,这会使相等性始终 return
false
?
In order to call
CheckOnSomething
, I need to pass a delegate toCatchSomething
. 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