Example #1
0
        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)));
        }