public static MethodBase GetBestFitMethod(MethodBase[] methods, object[] argValues)
        {
            int argCount = argValues.Length;
            var methodCandidates = methods
                .Select(m => new
                {
                    Method = m,
                    ParameterTypes = m.GetParameters()
                        .Select(p => p.ParameterType)
                        .ToArray()
                })
                .ToArray()
                ;

            var methodsWithSameArity = methodCandidates
                .Where(m => m.ParameterTypes.Length == argCount)
                .ToArray()
                ;
            if (methodsWithSameArity.Length == 0)
            {
                return null;
            }

            Type[] argTypes = argValues
                .Select(a => a.GetType())
                .ToArray()
                ;
            var weaklyCompatibleMethods = methodsWithSameArity
                .Where(m => CompareParameterTypes(argValues, argTypes, m.ParameterTypes, false))
                .ToArray()
                ;

            int weaklyCompatibleMethodCount = weaklyCompatibleMethods.Length;
            if (weaklyCompatibleMethodCount > 0)
            {
                if (weaklyCompatibleMethodCount == 1)
                {
                    return weaklyCompatibleMethods[0].Method;
                }

                var strictlyCompatibleMethods = weaklyCompatibleMethods
                    .Where(m => CompareParameterTypes(argValues, argTypes, m.ParameterTypes, true))
                    .ToArray()
                    ;
                if (strictlyCompatibleMethods.Length > 0)
                {
                    return strictlyCompatibleMethods[0].Method;
                }

                return weaklyCompatibleMethods[0].Method;
            }

            return null;
        }