public static MethodInfo FindMethod(this Type ownerType, string methodName, ClrMemberFlags methodFlags, params Type[] argumentTypes)
        {
            if (null == ownerType)
            {
                throw new ArgumentNullException(nameof(ownerType));
            }
            if (string.IsNullOrWhiteSpace(methodName))
            {
                throw new ArgumentNullException(nameof(methodName));
            }

            BindingFlags bindingFlags = BindingFlags.Default;

            if (methodFlags.HasFlag(ClrMemberFlags.Instance))
            {
                bindingFlags |= BindingFlags.Instance;
            }
            if (methodFlags.HasFlag(ClrMemberFlags.Static))
            {
                bindingFlags |= BindingFlags.Static;
            }
            if (methodFlags.HasFlag(ClrMemberFlags.Public))
            {
                bindingFlags |= BindingFlags.Public;
            }
            if (methodFlags.HasFlag(ClrMemberFlags.NonPublic))
            {
                bindingFlags |= BindingFlags.NonPublic;
            }

            return(ownerType.GetMethods(bindingFlags)
                   .Where(x => 0 == string.Compare(x.Name, methodName, StringComparison.OrdinalIgnoreCase))
                   .Where(x =>
            {
                var methodParameters = x.GetParameters();
                if (null == argumentTypes || 0 == argumentTypes.Length)
                {
                    return 0 == methodParameters.Length;
                }
                else
                {
                    if (argumentTypes.Length != methodParameters.Length)
                    {
                        return false;
                    }

                    for (int loop = 0; loop < methodParameters.Length; loop++)
                    {
                        if (!methodParameters[loop].ParameterType.IsAssignableFrom(argumentTypes[loop]))
                        {
                            return false;
                        }
                    }
                }

                return true;
            })
                   .FirstOrDefault());
        }
        public static IEnumerable <MethodInfo> FindMethods(this Type type, Func <MethodInfo, bool> predicate, ClrMemberFlags methodFlags = ClrMemberFlags.None)
        {
            if (null == type)
            {
                throw new ArgumentNullException(nameof(type));
            }

            return(from m in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)
                   where (
                       ClrMemberFlags.None == methodFlags ||
                       (
                           methodFlags.HasFlag(ClrMemberFlags.Instance) ? !m.IsStatic : true &&
                           methodFlags.HasFlag(ClrMemberFlags.Static) ? m.IsStatic : true &&
                           methodFlags.HasFlag(ClrMemberFlags.Public) ? m.IsPublic : true &&
                           methodFlags.HasFlag(ClrMemberFlags.NonPublic) ? !m.IsPublic : true &&
                           methodFlags.HasFlag(ClrMemberFlags.SpecialName) ? m.IsSpecialName : true
                       )
                       ) && predicate(m)
                   select m);
        }
        public static IEnumerable <Type> FindTypes <TBase>(string classNameSuffix = null, ClrMemberFlags typeFlags = ClrMemberFlags.Class)
        {
            Type typeOfTBase = typeof(TBase);

            return(ReflectionHelpers.FindTypes(t =>
            {
                return
                ClrMemberFlags.None == typeFlags ||
                (typeFlags.HasFlag(ClrMemberFlags.Class) ? t.IsClass : true &&
                 typeFlags.HasFlag(ClrMemberFlags.Concrete) ? !t.IsAbstract : true &&
                 typeFlags.HasFlag(ClrMemberFlags.NonPublic) ? t.IsNotPublic : true &&
                 typeFlags.HasFlag(ClrMemberFlags.Primitive) ? t.IsPrimitive : true &&
                 typeFlags.HasFlag(ClrMemberFlags.Public) ? t.IsPublic : true &&
                 typeFlags.HasFlag(ClrMemberFlags.SpecialName) ? t.IsSpecialName : true &&
                 typeFlags.HasFlag(ClrMemberFlags.NotSpecialName) ? !t.IsSpecialName : true) &&
                typeOfTBase.IsAssignableFrom(t)
                &&
                (
                    string.IsNullOrWhiteSpace(classNameSuffix) ||
                    t.Name.EndsWith(classNameSuffix, StringComparison.OrdinalIgnoreCase)
                );
            }));
        }