For a simple example, if I had some sort of button UI class, could I write a function that takes an expression that points to its Click
event handler:
SomeMethod<SomeButtonClass>(button => button.Click);
I'm trying to eliminate some magic strings currently being used for a system to make events awaitable. The code in question is derived from a blog post by Frank Krueger (a worthwhile read, if you want some background).
public static Task<TEventArgs> GetEventAsync<TEventArgs>(this object eventSource, string eventName) where TEventArgs : EventArgs {
//...
Type type = eventSource.GetType();
EventInfo ev = type.GetEvent(eventName);
//...
}
While the specifics inside probably aren't important, the full method allows you to use an Event
triggering as the completion source for a Task
, making it easier to manage with await
. For some class that raises an event, you can tie into a Task
based on that event with a simple call.
Task<EventArgs> eventTask = someEventCausingObject.GetEventAsync<EventArgs>("SomeEventHandler");
// traditionally used as someEventCausingObject.SomeEventHandler += ...;
await eventTask;
// Proceed back here when SomeEventHandler event is raised.
I have been using this happily for a couple projects, but it has its drawbacks, one of the biggest being the use of hard-coded event name string
s. This makes event name changes turn into runtime exceptions, and determining usage of the event is difficult.
I started trying to make a version that would allow the EventHandler
to be passed in as part of an Expression
with the goal of something like this:
await someEventCausingObject.GetEventAsync<EventCausingClass, EventArgs>(x => x.SomeEventHandler);
...with the corresponding method signature...
public static Task<TEventArgs> GetEventAsync<TSource, TEventArgs>(this TSource eventSource, Expression<Func<TSource, EventHandler>> eventHandlerExpression) where TEventArgs : EventArgs {
//...
}
Unfortunately, the lambda expression in the calling code causes a compile error:
Error CS0070: The event `SomeEventHandler' can only appear on the left hand side of += or -= when used outside of the type `EventCausingClass'.
This makes some sense given how event handlers are typically used, but I was hoping to find a better solution going forward than the pre-specified string name. It seems searches for combinations of "expression" and "eventhandler" all tend to be polluted with people describing lambda expressions for beginning +=
event handler assignment. I'm hoping I am missing something obvious here.