令我烦恼的一件事是,在默认的事件中,发件人是对象类型的,因此在使用它之前,几乎总是需要手动进行强制转换。幸运的是,由于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/