举一个简单的例子,如果我有某种按钮 UI 类,我可以编写一个函数来接受指向其的表达式吗?Click
事件处理程序:
SomeMethod<SomeButtonClass>(button => button.Click);
我正在尝试消除当前用于系统的一些魔法字符串,以使事件可等待。有问题的代码源自弗兰克·克鲁格的博客文章 http://praeclarum.org/post/45231096776/await-in-the-land-of-ios-drag-n-drop#alittletrickfunction(如果您想要一些背景知识,值得一读)。
public static Task<TEventArgs> GetEventAsync<TEventArgs>(this object eventSource, string eventName) where TEventArgs : EventArgs {
//...
Type type = eventSource.GetType();
EventInfo ev = type.GetEvent(eventName);
//...
}
虽然里面的细节可能并不重要,但完整的方法允许您使用Event
触发作为完成源Task
,使其更易于管理await
。对于某些引发事件的类,您可以绑定到Task
基于该事件,通过简单的调用。
Task<EventArgs> eventTask = someEventCausingObject.GetEventAsync<EventArgs>("SomeEventHandler");
// traditionally used as someEventCausingObject.SomeEventHandler += ...;
await eventTask;
// Proceed back here when SomeEventHandler event is raised.
我一直在几个项目中愉快地使用它,但它有它的缺点,最大的缺点之一是使用硬编码的事件名称string
s。这使得事件名称更改变成运行时异常,并且很难确定事件的使用情况。
我开始尝试制作一个版本,允许EventHandler
作为一部分传递Expression
目标是这样的:
await someEventCausingObject.GetEventAsync<EventCausingClass, EventArgs>(x => x.SomeEventHandler);
...具有相应的方法签名...
public static Task<TEventArgs> GetEventAsync<TSource, TEventArgs>(this TSource eventSource, Expression<Func<TSource, EventHandler>> eventHandlerExpression) where TEventArgs : EventArgs {
//...
}
不幸的是,调用代码中的 lambda 表达式会导致编译错误:
Error CS0070: The event `SomeEventHandler' can only appear on the left hand side of += or -= when used outside of the type `EventCausingClass'.
考虑到事件处理程序的通常使用方式,这是有一定道理的,但我希望找到一个比预先指定的字符串名称更好的解决方案。似乎对“表达式”和“事件处理程序”组合的搜索都倾向于被描述 lambda 表达式开头的人所污染。+=
事件处理程序分配。我希望我在这里遗漏了一些明显的东西。