Beispiel #1
0
        // Given a set of methods that match the base criteria, select a method based
        // upon an array of types.  This method should return null if no method matchs
        // the criteria.
        public static MethodBase SelectMethod(MethodBase[] match, Type[] types)
        {
            int i;
            int j;

            MethodBase[] candidates = (MethodBase[])match.Clone();

            // Find all the methods that can be described by the types parameter. 
            //  Remove all of them that cannot.
            int CurIdx = 0;
            for (i = 0; i < candidates.Length; i++)
            {
                ParameterInfo[] par = candidates[i].GetParameters();
                if (par.Length != types.Length)
                    continue;
                for (j = 0; j < types.Length; j++)
                {
                    Type pCls = par[j].ParameterType;
                    if (pCls == types[j])
                        continue;
                    if (pCls == typeof(Object))
                        continue;
                    if (pCls.GetTypeInfo().IsPrimitive)
                    {
                        if (!CanConvertPrimitive(types[j], pCls))
                            break;
                    }
                    else
                    {
                        if (!pCls.GetTypeInfo().IsAssignableFrom(types[j].GetTypeInfo()))
                            break;
                    }
                }
                if (j == types.Length)
                    candidates[CurIdx++] = candidates[i];
            }
            if (CurIdx == 0)
                return null;
            if (CurIdx == 1)
                return candidates[0];

            // Walk all of the methods looking the most specific method to invoke
            int currentMin = 0;
            bool ambig = false;
            int[] paramOrder = new int[types.Length];
            for (i = 0; i < types.Length; i++)
                paramOrder[i] = i;
            for (i = 1; i < CurIdx; i++)
            {
                int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder, null, candidates[i], paramOrder, null, types, null);
                if (newMin == 0)
                    ambig = true;
                else
                {
                    if (newMin == 2)
                    {
                        currentMin = i;
                        ambig = false;
                        currentMin = i;
                    }
                }
            }
            if (ambig)
                throw new AmbiguousMatchException(SR.Arg_AmbiguousMatchException);
            return candidates[currentMin];
        }
Beispiel #2
0
        // Given a set of methods that match the base criteria, select a method based
        // upon an array of types.  This method should return null if no method matchs
        // the criteria.
        public sealed override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
        {
            int i;
            int j;

            Type[] realTypes = new Type[types.Length];
            for (i = 0; i < types.Length; i++)
            {
                realTypes[i] = types[i].UnderlyingSystemType;
                if (!(realTypes[i].IsRuntimeImplemented()))
                    throw new ArgumentException(SR.Arg_MustBeType, nameof(types));
            }
            types = realTypes;

            // We don't automatically jump out on exact match.
            if (match == null || match.Length == 0)
                throw new ArgumentException(SR.Arg_EmptyArray, nameof(match));

            MethodBase[] candidates = (MethodBase[])match.Clone();

            // Find all the methods that can be described by the types parameter. 
            //  Remove all of them that cannot.
            int CurIdx = 0;
            for (i = 0; i < candidates.Length; i++)
            {
                ParameterInfo[] par = candidates[i].GetParametersNoCopy();
                if (par.Length != types.Length)
                    continue;
                for (j = 0; j < types.Length; j++)
                {
                    Type pCls = par[j].ParameterType;
                    if (pCls == types[j])
                        continue;
                    if (pCls == CommonRuntimeTypes.Object)
                        continue;
                    if (pCls.IsPrimitive)
                    {
                        if (!(types[j].UnderlyingSystemType.IsRuntimeImplemented()) ||
                            !CanConvertPrimitive(types[j].UnderlyingSystemType, pCls.UnderlyingSystemType))
                            break;
                    }
                    else
                    {
                        if (!pCls.IsAssignableFrom(types[j]))
                            break;
                    }
                }
                if (j == types.Length)
                    candidates[CurIdx++] = candidates[i];
            }
            if (CurIdx == 0)
                return null;
            if (CurIdx == 1)
                return candidates[0];

            // Walk all of the methods looking the most specific method to invoke
            int currentMin = 0;
            bool ambig = false;
            int[] paramOrder = new int[types.Length];
            for (i = 0; i < types.Length; i++)
                paramOrder[i] = i;
            for (i = 1; i < CurIdx; i++)
            {
                int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder, null, candidates[i], paramOrder, null, types, null);
                if (newMin == 0)
                    ambig = true;
                else
                {
                    if (newMin == 2)
                    {
                        currentMin = i;
                        ambig = false;
                        currentMin = i;
                    }
                }
            }
            if (ambig)
                throw new AmbiguousMatchException(SR.Arg_AmbiguousMatchException);
            return candidates[currentMin];
        }
Beispiel #3
0
        // This method is passed a set of methods and must choose the best
        // fit.  The methods all have the same number of arguments and the object
        // array args.  On exit, this method will choice the best fit method
        // and coerce the args to match that method.  By match, we mean all primitive
        // arguments are exact matchs and all object arguments are exact or subclasses
        // of the target.  If the target OR is an interface, the object must implement
        // that interface.  There are a couple of exceptions
        // thrown when a method cannot be returned.  If no method matchs the args and
        // ArgumentException is thrown.  If multiple methods match the args then 
        // an AmbiguousMatchException is thrown.
        // 
        // The most specific match will be selected.  
        // 
        public static MethodBase BindToMethod(MethodBase[] match, ref Object[] args)
        {
            if (match == null || match.Length == 0)
                throw new ArgumentException(SR.Arg_EmptyArray, "match");
            Contract.EndContractBlock();

            MethodBase[] candidates = (MethodBase[])match.Clone();

            int i;
            int j;

            #region Map named parameters to candidate parameter postions
            // We are creating an paramOrder array to act as a mapping
            //  between the order of the args and the actual order of the
            //  parameters in the method.  This order may differ because
            //  named parameters (names) may change the order.  If names
            //  is not provided, then we assume the default mapping (0,1,...)
            int[][] paramOrder = new int[candidates.Length][];

            for (i = 0; i < candidates.Length; i++)
            {
                ParameterInfo[] par = candidates[i].GetParameters();

                // args.Length + 1 takes into account the possibility of a last paramArray that can be omitted
                paramOrder[i] = new int[(par.Length > args.Length) ? par.Length : args.Length];

                // Default mapping
                for (j = 0; j < args.Length; j++)
                    paramOrder[i][j] = j;
            }
            #endregion

            Type[] paramArrayTypes = new Type[candidates.Length];

            Type[] argTypes = new Type[args.Length];

            #region Cache the type of the provided arguments
            // object that contain a null are treated as if they were typeless (but match either object 
            // references or value classes).  We mark this condition by placing a null in the argTypes array.
            for (i = 0; i < args.Length; i++)
            {
                if (args[i] != null)
                {
                    argTypes[i] = args[i].GetType();
                }
            }
            #endregion


            // Find the method that matches...
            int CurIdx = 0;

            Type paramArrayType = null;

            #region Filter methods by parameter count and type
            for (i = 0; i < candidates.Length; i++)
            {
                paramArrayType = null;

                // If we have named parameters then we may have a hole in the candidates array.
                if (candidates[i] == null)
                    continue;

                // Validate the parameters.
                ParameterInfo[] par = candidates[i].GetParameters();

                #region Match method by parameter count
                if (par.Length == 0)
                {
                    #region No formal parameters
                    if (args.Length != 0)
                    {
                        if ((candidates[i].CallingConvention & CallingConventions.VarArgs) == 0)
                            continue;
                    }

                    // This is a valid routine so we move it up the candidates list.
                    paramOrder[CurIdx] = paramOrder[i];
                    candidates[CurIdx++] = candidates[i];

                    continue;
                    #endregion
                }
                else if (par.Length > args.Length)
                {
                    #region Shortage of provided parameters
                    // If the number of parameters is greater than the number of args then 
                    // we are in the situation were we may be using default values.
                    for (j = args.Length; j < par.Length - 1; j++)
                    {
                        if (!par[j].HasDefaultValue)
                            break;
                    }

                    if (j != par.Length - 1)
                        continue;

                    if (!par[j].HasDefaultValue)
                    {
                        if (!par[j].ParameterType.IsArray)
                            continue;

                        if (!HasParamArrayAttribute(par[j]))
                            continue;

                        paramArrayType = par[j].ParameterType.GetElementType();
                    }
                    #endregion
                }
                else if (par.Length < args.Length)
                {
                    #region Excess provided parameters
                    // test for the ParamArray case
                    int lastArgPos = par.Length - 1;

                    if (!par[lastArgPos].ParameterType.IsArray)
                        continue;

                    if (!HasParamArrayAttribute(par[lastArgPos]))
                        continue;

                    if (paramOrder[i][lastArgPos] != lastArgPos)
                        continue;

                    paramArrayType = par[lastArgPos].ParameterType.GetElementType();
                    #endregion
                }
                else
                {
                    #region Test for paramArray, save paramArray type
                    int lastArgPos = par.Length - 1;

                    if (par[lastArgPos].ParameterType.IsArray
                        && HasParamArrayAttribute(par[lastArgPos])
                        && paramOrder[i][lastArgPos] == lastArgPos)
                    {
                        if (!par[lastArgPos].ParameterType.GetTypeInfo().IsAssignableFrom(argTypes[lastArgPos].GetTypeInfo()))
                            paramArrayType = par[lastArgPos].ParameterType.GetElementType();
                    }
                    #endregion
                }
                #endregion

                Type pCls = null;
                int argsToCheck = (paramArrayType != null) ? par.Length - 1 : args.Length;

                #region Match method by parameter type
                for (j = 0; j < argsToCheck; j++)
                {
                    #region Classic argument coersion checks
                    // get the formal type
                    pCls = par[j].ParameterType;

                    if (pCls.IsByRef)
                        pCls = pCls.GetElementType();

                    // the type is the same
                    if (pCls == argTypes[paramOrder[i][j]])
                        continue;

                    // the argument was null, so it matches with everything
                    if (args[paramOrder[i][j]] == null)
                        continue;

                    // the type is Object, so it will match everything
                    if (pCls == typeof(Object))
                        continue;

                    // now do a "classic" type check
                    if (pCls.GetTypeInfo().IsPrimitive)
                    {
                        if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]], pCls))
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (argTypes[paramOrder[i][j]] == null)
                            continue;

                        if (!pCls.GetTypeInfo().IsAssignableFrom(argTypes[paramOrder[i][j]].GetTypeInfo()))
                        {
                            break;
                        }
                    }
                    #endregion
                }

                if (paramArrayType != null && j == par.Length - 1)
                {
                    #region Check that excess arguments can be placed in the param array

                    // Legacy: It's so pathetic that we go to all this trouble let "widening-compatible" params arguments through this screen 
                    // only to end up blowing up with an InvalidCastException anyway because we use Array.Copy() to do the actual copy down below.
                    // Ah, the joys of backward compatibility...
                    for (; j < args.Length; j++)
                    {
                        if (paramArrayType.GetTypeInfo().IsPrimitive)
                        {
                            if (argTypes[j] == null || !CanConvertPrimitiveObjectToType(args[j], paramArrayType))
                                break;
                        }
                        else
                        {
                            if (argTypes[j] == null)
                                continue;

                            if (!paramArrayType.GetTypeInfo().IsAssignableFrom(argTypes[j].GetTypeInfo()))
                            {
                                break;
                            }
                        }
                    }
                    #endregion
                }
                #endregion

                if (j == args.Length)
                {
                    #region This is a valid routine so we move it up the candidates list
                    paramOrder[CurIdx] = paramOrder[i];
                    paramArrayTypes[CurIdx] = paramArrayType;
                    candidates[CurIdx++] = candidates[i];
                    #endregion
                }
            }
            #endregion

            // If we didn't find a method 
            if (CurIdx == 0)
                throw new MissingMethodException(SR.MissingMember);

            if (CurIdx == 1)
            {
                #region Found only one method
                // If the parameters and the args are not the same length or there is a paramArray
                //  then we need to create a argument array.
                ParameterInfo[] parms = candidates[0].GetParameters();

                if (parms.Length == args.Length)
                {
                    if (paramArrayTypes[0] != null)
                    {
                        Object[] objs = new Object[parms.Length];
                        int lastPos = parms.Length - 1;
                        Array.Copy(args, 0, objs, 0, lastPos);
                        objs[lastPos] = Array.CreateInstance(paramArrayTypes[0], 1);
                        ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
                        args = objs;
                    }
                }
                else if (parms.Length > args.Length)
                {
                    Object[] objs = new Object[parms.Length];

                    for (i = 0; i < args.Length; i++)
                        objs[i] = args[i];

                    for (; i < parms.Length - 1; i++)
                        objs[i] = parms[i].DefaultValue;

                    if (paramArrayTypes[0] != null)
                        objs[i] = Array.CreateInstance(paramArrayTypes[0], 0); // create an empty array for the 

                    else
                        objs[i] = parms[i].DefaultValue;

                    args = objs;
                }
                else
                {
                    if ((candidates[0].CallingConvention & CallingConventions.VarArgs) == 0)
                    {
                        Object[] objs = new Object[parms.Length];
                        int paramArrayPos = parms.Length - 1;
                        Array.Copy(args, 0, objs, 0, paramArrayPos);
                        objs[paramArrayPos] = Array.CreateInstance(paramArrayTypes[0], args.Length - paramArrayPos);
                        Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos);
                        args = objs;
                    }
                }
                #endregion

                return candidates[0];
            }

            int currentMin = 0;
            bool ambig = false;
            for (i = 1; i < CurIdx; i++)
            {
                #region Walk all of the methods looking the most specific method to invoke
                int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder[currentMin], paramArrayTypes[currentMin],
                                                    candidates[i], paramOrder[i], paramArrayTypes[i], argTypes, args);

                if (newMin == 0)
                {
                    ambig = true;
                }
                else if (newMin == 2)
                {
                    currentMin = i;
                    ambig = false;
                }
                #endregion
            }

            if (ambig)
                throw new AmbiguousMatchException(SR.Arg_AmbiguousMatchException);

            // If the parameters and the args are not the same length or there is a paramArray
            //  then we need to create a argument array.
            ParameterInfo[] parameters = candidates[currentMin].GetParameters();
            if (parameters.Length == args.Length)
            {
                if (paramArrayTypes[currentMin] != null)
                {
                    Object[] objs = new Object[parameters.Length];
                    int lastPos = parameters.Length - 1;
                    Array.Copy(args, 0, objs, 0, lastPos);
                    objs[lastPos] = Array.CreateInstance(paramArrayTypes[currentMin], 1);
                    ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
                    args = objs;
                }
            }
            else if (parameters.Length > args.Length)
            {
                Object[] objs = new Object[parameters.Length];

                for (i = 0; i < args.Length; i++)
                    objs[i] = args[i];

                for (; i < parameters.Length - 1; i++)
                    objs[i] = parameters[i].DefaultValue;

                if (paramArrayTypes[currentMin] != null)
                {
                    objs[i] = Array.CreateInstance(paramArrayTypes[currentMin], 0);
                }
                else
                {
                    objs[i] = parameters[i].DefaultValue;
                }

                args = objs;
            }
            else
            {
                if ((candidates[currentMin].CallingConvention & CallingConventions.VarArgs) == 0)
                {
                    Object[] objs = new Object[parameters.Length];
                    int paramArrayPos = parameters.Length - 1;
                    Array.Copy(args, 0, objs, 0, paramArrayPos);
                    objs[paramArrayPos] = Array.CreateInstance(paramArrayTypes[currentMin], args.Length - paramArrayPos);
                    Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos);
                    args = objs;
                }
            }

            return candidates[currentMin];
        }
Beispiel #4
0
        // This method is passed a set of methods and must choose the best
        // fit.  The methods all have the same number of arguments and the object
        // array args.  On exit, this method will choice the best fit method
        // and coerce the args to match that method.  By match, we mean all primitive
        // arguments are exact matchs and all object arguments are exact or subclasses
        // of the target.  If the target OR is an interface, the object must implement
        // that interface.  There are a couple of exceptions
        // thrown when a method cannot be returned.  If no method matchs the args and
        // ArgumentException is thrown.  If multiple methods match the args then 
        // an AmbiguousMatchException is thrown.
        // 
        // The most specific match will be selected.  
        // 
        public sealed override MethodBase BindToMethod(
            BindingFlags bindingAttr, MethodBase[] match, ref Object[] args,
            ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, out Object state)
        {
            if (match == null || match.Length == 0)
                throw new ArgumentException(SR.Arg_EmptyArray, nameof(match));

            MethodBase[] candidates = (MethodBase[])match.Clone();

            int i;
            int j;

            state = null;

            #region Map named parameters to candidate parameter postions
            // We are creating an paramOrder array to act as a mapping
            //  between the order of the args and the actual order of the
            //  parameters in the method.  This order may differ because
            //  named parameters (names) may change the order.  If names
            //  is not provided, then we assume the default mapping (0,1,...)
            int[][] paramOrder = new int[candidates.Length][];

            for (i = 0; i < candidates.Length; i++)
            {
                ParameterInfo[] par = candidates[i].GetParametersNoCopy();

                // args.Length + 1 takes into account the possibility of a last paramArray that can be omitted
                paramOrder[i] = new int[(par.Length > args.Length) ? par.Length : args.Length];

                if (names == null)
                {
                    // Default mapping
                    for (j = 0; j < args.Length; j++)
                        paramOrder[i][j] = j;
                }
                else
                {
                    // Named parameters, reorder the mapping.  If CreateParamOrder fails, it means that the method
                    // doesn't have a name that matchs one of the named parameters so we don't consider it any further.
                    if (!CreateParamOrder(paramOrder[i], par, names))
                        candidates[i] = null;
                }
            }
            #endregion

            Type[] paramArrayTypes = new Type[candidates.Length];

            Type[] argTypes = new Type[args.Length];

            #region Cache the type of the provided arguments
            // object that contain a null are treated as if they were typeless (but match either object 
            // references or value classes).  We mark this condition by placing a null in the argTypes array.
            for (i = 0; i < args.Length; i++)
            {
                if (args[i] != null)
                {
                    argTypes[i] = args[i].GetType();
                }
            }
            #endregion


            // Find the method that matches...
            int CurIdx = 0;
            bool defaultValueBinding = ((bindingAttr & BindingFlags.OptionalParamBinding) != 0);

            Type paramArrayType = null;

            #region Filter methods by parameter count and type
            for (i = 0; i < candidates.Length; i++)
            {
                paramArrayType = null;

                // If we have named parameters then we may have a hole in the candidates array.
                if (candidates[i] == null)
                    continue;

                // Validate the parameters.
                ParameterInfo[] par = candidates[i].GetParametersNoCopy();

                #region Match method by parameter count
                if (par.Length == 0)
                {
                    #region No formal parameters
                    if (args.Length != 0)
                    {
                        if ((candidates[i].CallingConvention & CallingConventions.VarArgs) == 0)
                            continue;
                    }

                    // This is a valid routine so we move it up the candidates list.
                    paramOrder[CurIdx] = paramOrder[i];
                    candidates[CurIdx++] = candidates[i];

                    continue;
                    #endregion
                }
                else if (par.Length > args.Length)
                {
                    #region Shortage of provided parameters
                    // If the number of parameters is greater than the number of args then 
                    // we are in the situation were we may be using default values.
                    for (j = args.Length; j < par.Length - 1; j++)
                    {
                        if (par[j].DefaultValue == System.DBNull.Value)
                            break;
                    }

                    if (j != par.Length - 1)
                        continue;

                    if (par[j].DefaultValue == System.DBNull.Value)
                    {
                        if (!par[j].ParameterType.IsArray)
                            continue;

                        if (!par[j].IsDefined(typeof(ParamArrayAttribute), true))
                            continue;

                        paramArrayType = par[j].ParameterType.GetElementType();
                    }
                    #endregion
                }
                else if (par.Length < args.Length)
                {
                    #region Excess provided parameters
                    // test for the ParamArray case
                    int lastArgPos = par.Length - 1;

                    if (!par[lastArgPos].ParameterType.IsArray)
                        continue;

                    if (!par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true))
                        continue;

                    if (paramOrder[i][lastArgPos] != lastArgPos)
                        continue;

                    paramArrayType = par[lastArgPos].ParameterType.GetElementType();
                    #endregion
                }
                else
                {
                    #region Test for paramArray, save paramArray type
                    int lastArgPos = par.Length - 1;

                    if (par[lastArgPos].ParameterType.IsArray
                        && par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true)
                        && paramOrder[i][lastArgPos] == lastArgPos)
                    {
                        if (!par[lastArgPos].ParameterType.IsAssignableFrom(argTypes[lastArgPos]))
                            paramArrayType = par[lastArgPos].ParameterType.GetElementType();
                    }
                    #endregion
                }
                #endregion

                Type pCls = null;
                int argsToCheck = (paramArrayType != null) ? par.Length - 1 : args.Length;

                #region Match method by parameter type
                for (j = 0; j < argsToCheck; j++)
                {
                    #region Classic argument coersion checks
                    // get the formal type
                    pCls = par[j].ParameterType;

                    if (pCls.IsByRef)
                        pCls = pCls.GetElementType();

                    // the type is the same
                    if (pCls == argTypes[paramOrder[i][j]])
                        continue;

                    // a default value is available
                    if (defaultValueBinding && args[paramOrder[i][j]] == Type.Missing)
                        continue;

                    // the argument was null, so it matches with everything
                    if (args[paramOrder[i][j]] == null)
                        continue;

                    // the type is Object, so it will match everything
                    if (pCls == CommonRuntimeTypes.Object)
                        continue;

                    // now do a "classic" type check
                    if (pCls.IsPrimitive)
                    {
                        if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]], pCls))
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (argTypes[paramOrder[i][j]] == null)
                            continue;

                        if (!pCls.IsAssignableFrom(argTypes[paramOrder[i][j]]))
                        {
                            if (argTypes[paramOrder[i][j]].IsCOMObject)
                            {
                                if (pCls.IsInstanceOfType(args[paramOrder[i][j]]))
                                    continue;
                            }
                            break;
                        }
                    }
                    #endregion
                }

                if (paramArrayType != null && j == par.Length - 1)
                {
                    #region Check that excess arguments can be placed in the param array
                    for (; j < args.Length; j++)
                    {
                        if (paramArrayType.IsPrimitive)
                        {
                            if (argTypes[j] == null || !CanConvertPrimitiveObjectToType(args[j], paramArrayType))
                                break;
                        }
                        else
                        {
                            if (argTypes[j] == null)
                                continue;

                            if (!paramArrayType.IsAssignableFrom(argTypes[j]))
                            {
                                if (argTypes[j].IsCOMObject)
                                {
                                    if (paramArrayType.IsInstanceOfType(args[j]))
                                        continue;
                                }

                                break;
                            }
                        }
                    }
                    #endregion
                }
                #endregion

                if (j == args.Length)
                {
                    #region This is a valid routine so we move it up the candidates list
                    paramOrder[CurIdx] = paramOrder[i];
                    paramArrayTypes[CurIdx] = paramArrayType;
                    candidates[CurIdx++] = candidates[i];
                    #endregion
                }
            }
            #endregion

            // If we didn't find a method 
            if (CurIdx == 0)
                throw new MissingMethodException(SR.MissingMember);

            if (CurIdx == 1)
            {
                #region Found only one method
                if (names != null)
                {
                    state = new BinderState((int[])paramOrder[0].Clone(), args.Length, paramArrayTypes[0] != null);
                    ReorderParams(paramOrder[0], args);
                }

                // If the parameters and the args are not the same length or there is a paramArray
                //  then we need to create a argument array.
                ParameterInfo[] parms = candidates[0].GetParametersNoCopy();

                if (parms.Length == args.Length)
                {
                    if (paramArrayTypes[0] != null)
                    {
                        Object[] objs = new Object[parms.Length];
                        int lastPos = parms.Length - 1;
                        Array.Copy(args, 0, objs, 0, lastPos);
                        objs[lastPos] = Array.CreateInstance(paramArrayTypes[0], 1);
                        ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
                        args = objs;
                    }
                }
                else if (parms.Length > args.Length)
                {
                    Object[] objs = new Object[parms.Length];

                    for (i = 0; i < args.Length; i++)
                        objs[i] = args[i];

                    for (; i < parms.Length - 1; i++)
                        objs[i] = parms[i].DefaultValue;

                    if (paramArrayTypes[0] != null)
                        objs[i] = Array.CreateInstance(paramArrayTypes[0], 0); // create an empty array for the 

                    else
                        objs[i] = parms[i].DefaultValue;

                    args = objs;
                }
                else
                {
                    if ((candidates[0].CallingConvention & CallingConventions.VarArgs) == 0)
                    {
                        Object[] objs = new Object[parms.Length];
                        int paramArrayPos = parms.Length - 1;
                        Array.Copy(args, 0, objs, 0, paramArrayPos);
                        objs[paramArrayPos] = Array.CreateInstance(paramArrayTypes[0], args.Length - paramArrayPos);
                        Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos);
                        args = objs;
                    }
                }
                #endregion

                return candidates[0];
            }

            int currentMin = 0;
            bool ambig = false;
            for (i = 1; i < CurIdx; i++)
            {
                #region Walk all of the methods looking the most specific method to invoke
                int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder[currentMin], paramArrayTypes[currentMin],
                                                    candidates[i], paramOrder[i], paramArrayTypes[i], argTypes, args);

                if (newMin == 0)
                {
                    ambig = true;
                }
                else if (newMin == 2)
                {
                    currentMin = i;
                    ambig = false;
                }
                #endregion
            }

            if (ambig)
                throw new AmbiguousMatchException(SR.Arg_AmbiguousMatchException);

            // Reorder (if needed)
            if (names != null)
            {
                state = new BinderState((int[])paramOrder[currentMin].Clone(), args.Length, paramArrayTypes[currentMin] != null);
                ReorderParams(paramOrder[currentMin], args);
            }

            // If the parameters and the args are not the same length or there is a paramArray
            //  then we need to create a argument array.
            ParameterInfo[] parameters = candidates[currentMin].GetParametersNoCopy();
            if (parameters.Length == args.Length)
            {
                if (paramArrayTypes[currentMin] != null)
                {
                    Object[] objs = new Object[parameters.Length];
                    int lastPos = parameters.Length - 1;
                    Array.Copy(args, 0, objs, 0, lastPos);
                    objs[lastPos] = Array.CreateInstance(paramArrayTypes[currentMin], 1);
                    ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
                    args = objs;
                }
            }
            else if (parameters.Length > args.Length)
            {
                Object[] objs = new Object[parameters.Length];

                for (i = 0; i < args.Length; i++)
                    objs[i] = args[i];

                for (; i < parameters.Length - 1; i++)
                    objs[i] = parameters[i].DefaultValue;

                if (paramArrayTypes[currentMin] != null)
                {
                    objs[i] = Array.CreateInstance(paramArrayTypes[currentMin], 0);
                }
                else
                {
                    objs[i] = parameters[i].DefaultValue;
                }

                args = objs;
            }
            else
            {
                if ((candidates[currentMin].CallingConvention & CallingConventions.VarArgs) == 0)
                {
                    Object[] objs = new Object[parameters.Length];
                    int paramArrayPos = parameters.Length - 1;
                    Array.Copy(args, 0, objs, 0, paramArrayPos);
                    objs[paramArrayPos] = Array.CreateInstance(paramArrayTypes[currentMin], args.Length - paramArrayPos);
                    Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos);
                    args = objs;
                }
            }

            return candidates[currentMin];
        }