/// <summary> /// Subscribes to the specified event. /// </summary> /// <param name="target">The object that publishes the event.</param> /// <param name="eventInfo">The event to which we subscribe.</param> public EventArgsTask(object target, EventInfo eventInfo) { _tcs = new TaskCompletionSource <TEventArgs>(); _target = target; _eventInfo = eventInfo; var eventCompletedMethod = ReflectionShim.GetMethod(GetType(), "EventCompleted"); _subscription = ReflectionShim.CreateDelegate(eventInfo.EventHandlerType, this, eventCompletedMethod); eventInfo.AddEventHandler(target, _subscription); }
/// <summary> /// Gets a task that will complete the next time an event is raised. The event type must follow the standard <c>void EventHandlerType(object, TResult)</c> pattern. Be mindful of race conditions (i.e., if the event is raised immediately before this method is called, your task may never complete). /// </summary> /// <param name="target">The object that publishes the event.</param> /// <returns>The event args.</returns> public static Task <TResult> FromEvent(object target) { // Try to look up an event that has the same name as the TResult type (stripping the trailing "EventArgs"). var type = target.GetType(); var resultType = typeof(TResult); var resultName = resultType.Name; if (resultName.EndsWith("EventArgs", StringComparison.Ordinal)) { var eventInfo = ReflectionShim.GetEvent(type, resultName.Remove(resultName.Length - 9)); if (eventInfo != null) { return(new EventArgsTask <TResult>(target, eventInfo).Task); } } // Try to match to any event with the correct signature. EventInfo match = null; foreach (var eventInfo in ReflectionShim.GetEvents(type)) { var invoke = ReflectionShim.GetMethod(eventInfo.EventHandlerType, "Invoke"); if (invoke.ReturnType != typeof(void)) { continue; } var parameters = invoke.GetParameters(); if (parameters.Length != 2 || parameters[0].ParameterType != typeof(object) || parameters[1].ParameterType != resultType) { continue; } if (match != null) { throw new InvalidOperationException("Found multiple matching events on type " + target.GetType().FullName); } match = eventInfo; } if (match == null) { throw new InvalidOperationException("Could not find a matching event on type " + target.GetType().FullName); } return(new EventArgsTask <TResult>(target, match).Task); }