public static string[] FindEvents(Type senderType, Type argsType, Func <string, bool> exclude) { var found = MatchedEventNames.GetOrAdd(new Tuple <Type, Type>(senderType, argsType), tuple => { var events = CandidateEvents.GetOrAdd(senderType, t => { return(t.GetEvents(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy) //we can only look for events handlers with generic types because that is the only // way that we can try to find a matching event based on the arg type passed in .Where(x => x.EventHandlerType?.IsGenericType ?? false) .Select(x => new EventInfoArgs(x, x.EventHandlerType !.GetGenericArguments())) //we are only looking for event handlers that have more than one generic argument .Where(x => { if (x.GenericArgs.Length == 1) { return true; } //special case for our own TypedEventHandler if (x.EventInfo.EventHandlerType?.GetGenericTypeDefinition() == typeof(TypedEventHandler <,>) && x.GenericArgs.Length == 2) { return true; } return false; }) .ToArray()); });
/// <summary> /// Finds the event name on the sender that matches the args type /// </summary> /// <param name="senderType"></param> /// <param name="argsType"></param> /// <param name="exclude"> /// A filter to exclude matched event names, this filter should return true to exclude the event name from being matched /// </param> /// <returns> /// null if not found or an ambiguous match /// </returns> public static Attempt <EventNameExtractorResult> FindEvent(Type senderType, Type argsType, Func <string, bool> exclude) { var found = MatchedEventNames.GetOrAdd(new Tuple <Type, Type>(senderType, argsType), tuple => { var events = CandidateEvents.GetOrAdd(senderType, t => { return(t.GetEvents(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) //we can only look for events handlers with generic types because that is the only // way that we can try to find a matching event based on the arg type passed in .Where(x => x.EventHandlerType.IsGenericType) .Select(x => new EventInfoArgs(x, x.EventHandlerType.GetGenericArguments())) //we are only looking for event handlers that have more than one generic argument .Where(x => { if (x.GenericArgs.Length == 1) { return true; } //special case for our own TypedEventHandler if (x.EventInfo.EventHandlerType.GetGenericTypeDefinition() == typeof(TypedEventHandler <,>) && x.GenericArgs.Length == 2) { return true; } return false; }) .ToArray()); }); return(events.Where(x => { if (x.GenericArgs.Length == 1 && x.GenericArgs[0] == tuple.Item2) { return true; } //special case for our own TypedEventHandler if (x.EventInfo.EventHandlerType.GetGenericTypeDefinition() == typeof(TypedEventHandler <,>) && x.GenericArgs.Length == 2 && x.GenericArgs[1] == tuple.Item2) { return true; } return false; }).Select(x => x.EventInfo.Name).ToArray()); }); var filtered = found.Where(x => exclude(x) == false).ToArray(); if (filtered.Length == 0) { return(Attempt.Fail(new EventNameExtractorResult(EventNameExtractorError.NoneFound))); } if (filtered.Length == 1) { return(Attempt.Succeed(new EventNameExtractorResult(filtered[0]))); } //there's more than one left so it's ambiguous! return(Attempt.Fail(new EventNameExtractorResult(EventNameExtractorError.Ambiguous))); }