【问题标题】:How to cast EventHandler<T> to EventHandler<EventArgs>?如何将 EventHandler<T> 转换为 EventHandler<EventArgs>?
【发布时间】:2015-04-15 18:00:58
【问题描述】:

我正在创建一个集中式事件聚合器,它保留一个接受 EventHandler 委托的注册表。聚合器类本身不是泛型的,但是注册方法是:

public void RegisterHandler<T>(EventHandler<T> handler) where T : EventArgs
{
    Debug.Assert(handler != null);
    if (handler != null)
    {
        if (this._eventRegistry != null)
        {
            this._eventRegistry.AddValue(typeof(T), handler);
        }
        else { /* Do nothing. */ }
    }
    else 
    { 
        throw new ArgumentNullException(ReflectionUtilities.GetVariableName(() => handler)); 
    }
}

目的是允许从 EventArgs 派生的任何类型的注册表。但是注册表(一种字典)接受 EventArgs 类型的 EventHandler 而不是 T 类型的 EventHandler,其中 T 是 EventArgs。

线

this._eventRegistry.AddValue(typeof(T), handler);

不会编译,因为它说它有一些无效的参数(特别是“处理程序”)。如果我将该参数更改为

this._eventRegistry.AddValue(typeof(T), handler as EventHandler<EventArgs>);

然后代码编译但参数 'handler' 有一个空值。

同样,如果我这样做:

EventHandler<EventArgs> eventHandler = handler as EventHandler<EventArgs>;

那么 'eventHandler' 为空。

如果我知道 T 被限制为 EventArgs 的类型或子类型,我该如何转换

EventHandler<T>

EventHandler<EventArgs>

?

【问题讨论】:

  • EventHandler&lt;T&gt;T 上是不变的。代表最接近的是Delegate 类。使您的字典成为从类型到委托(或某些包装器)的映射。
  • 为什么不用RegisterHandler(EventArgs) 而不是泛型方法?
  • @devundef 你的意思是RegisterHandler(EventHandler&lt;EventArgs&gt;)?该方法需要对方法的引用,以便稍后调用。

标签: c# casting event-handling


【解决方案1】:

您不能将 EventHandler&lt;T&gt; 转换为 EventHandler&lt;EventArgs&gt;。一个有点丑陋但简单的解决方法是更改​​这行代码:

this._eventRegistry.AddValue(typeof(T), handler);

this._eventRegistry.AddValue(typeof(T), (sender, evt) => handler(sender, (T)evt));

【讨论】:

  • 您创建的代码将编译,但它只会在运行时失败,这正是它不允许您首先转换处理程序的原因(将一个视为另一个根本不是适当的转换)。
  • @Servy 我假设实现的EventRegistry 类只会在事件实际上是T 类型时调用处理程序。
  • @Alex 只是更新,以防您有兴趣。使用以System.MulticastDelegate 作为其值的常规字典也可以完成相同的操作。然后,由于这些方法只接受特定类型的参数,因此可以将它们转换回泛型类型而不会失败。
猜你喜欢
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多