令我烦恼的一件事是,在默认的事件中,发件人是对象类型的,因此在使用它之前,几乎总是需要手动进行强制转换。幸运的是,由于VB现在还支持委托(delegate)中的方差,因此我们可以通过强类型化发送者的方式来更新事件的签名,请参见:Event parameter; "sender as Object", or "sender as T"?

不幸的是,这不适用于发送者为object类型的现有已声明事件。

现在,一种解决方案当然是生成一个伪造的EventHandler,它在内部为您处理转换。我做了一个简单的例子,请参见:

struct EventHandler<TSender, TEventArgs>
    where TEventArgs: EventArgs
{
    private readonly Action<TSender, TEventArgs> _delegate;

    public EventHandler(Action<TSender, TEventArgs> @delegate)
    {
        if (@delegate == null)
            throw new ArgumentNullException("@delegate");

        _delegate = @delegate;
    }

    public static implicit operator EventHandler<TEventArgs>(EventHandler<TSender, TEventArgs> eventHandler)
    {
        return new EventHandler<TEventArgs>(eventHandler.Execute);
    }

    private void Execute(object sender, EventArgs e)
    {
        TSender typedSender = (TSender)sender;
        TEventArgs typedEventArgs = (TEventArgs)e;

        _delegate(typedSender, typedEventArgs);
    }
}

可以像您期望的那样使用它:
class Program
{
    event EventHandler<EventArgs> Test;

    static void Main(string[] args)
    {
        new Program().Main();
    }

    void Main()
    {
        Test += new EventHandler<Program, EventArgs>(TestEventHandler);

        Test(this, EventArgs.Empty);
    }

    void TestEventHandler(Program sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

现在,如果我真的想使用此功能,则需要完成很多工作。 (该结构的行为应与原始委托(delegate)相同)。但是我确实感觉要么已经有一个很好的实现方案,要么就没有实现方案了,因为我忽略了一些主要的缺点。

谁能回答我上述问题?还有其他提示吗?

最佳答案

我想不出任何解决方案都比代码少

var original = (OriginalType)sender;

另外,如果class是您的类,则没有什么会阻止您创建自己的委托(delegate),而不是EventHandler委托(delegate)
delegate void EventHandler<in TSender, in TArgs>(TSender sender, TArgs args);

这在args和sender中是相反的

人们通常还具有引发事件的对象的引用,因此他们很少需要将事情从发送者那里拿走。您的情况可能吗?

编辑:由于您提到您正在处理不是由您编写的事件,因此修改委托(delegate)毫无疑问,并且您可能没有引用该对象,因此在这种情况下,您必须求助于发送者。现在,在您的解决方案中,您无法退订该事件。如果您对其进行修改以支持该功能,则必须保留对该结构的引用,这比简单的转换要花更多的功夫。我认为转换仍然是最干净的解决方案。

关于c# - C#中具有强类型发送者的EventHandler,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7709072/

10-08 22:25