示例#1
0
 public override MethodBase BindToMethod(
     BindingFlags bindingAttr,
     MethodBase[] match,
     ref object[] args,
     ParameterModifier[] modifiers,
     CultureInfo culture,
     string[] names,
     out object state
     )
 {
     // Store the arguments to the method in a state object.
     BinderState myBinderState = new BinderState();
     object[] arguments = new Object[args.Length];
     args.CopyTo(arguments, 0);
     myBinderState.args = arguments;
     state = myBinderState;
     if (match == null)
         throw new ArgumentNullException();
     // Find a method that has the same parameters as those of the args parameter.
     for (int i = 0; i < match.Length; i++)
     {
         // Count the number of parameters that match.
         int count = 0;
         ParameterInfo[] parameters = match[i].GetParameters();
         // Go on to the next method if the number of parameters do not match.
         if (args.Length != parameters.Length)
             continue;
         // Match each of the parameters that the user expects the method to have.
         for (int j = 0; j < args.Length; j++)
         {
             // If the names parameter is not null, then reorder args.
             if (names != null)
             {
                 if (names.Length != args.Length)
                     throw new ArgumentException("names and args must have the same number of elements.");
                 for (int k = 0; k < names.Length; k++)
                     if (String.Compare(parameters[j].Name, names[k].ToString()) == 0)
                         args[j] = myBinderState.args[k];
             }
             // Determine whether the types specified by the user can be converted to the parameter type.
             if (ChangeType(args[j], parameters[j].ParameterType, culture) != null)
                 count += 1;
             else
                 break;
         }
         // Determine whether the method has been found.
         if (count == args.Length)
             return match[i];
     }
     return null;
 }
示例#2
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        public 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(Environment.GetResourceString("Arg_EmptyArray"), "match");
            Contract.EndContractBlock();

            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 == typeof(Object))
                        continue;

                    // now do a "classic" type check
                    if (pCls.IsPrimitive) 
                    {
                        if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]],(RuntimeType)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], (RuntimeType)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(Environment.GetResourceString("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.UnsafeCreateInstance(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.UnsafeCreateInstance(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.UnsafeCreateInstance(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(Environment.GetResourceString("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.UnsafeCreateInstance(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.UnsafeCreateInstance(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.UnsafeCreateInstance(paramArrayTypes[currentMin], args.Length - paramArrayPos);
                    Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos);
                    args = objs;
                }
            }

            return candidates[currentMin];
        }
示例#3
0
        public override MethodBase BindToMethod(
            BindingFlags bindingAttr,
            MethodBase[] match,
            ref object[] args,
            ParameterModifier[] modifiers,
            CultureInfo culture,
            string[] names,
            out object state
            )
        {
            // Store the arguments to the method in a state object.
            BinderState myBinderState = new BinderState();

            object[] arguments = new Object[args.Length];
            args.CopyTo(arguments, 0);
            myBinderState.args = arguments;
            state = myBinderState;
            if (match == null)
            {
                throw new ArgumentNullException();
            }
            // Find a method that has the same parameters as those of the args parameter.
            for (int i = 0; i < match.Length; i++)
            {
                // Count the number of parameters that match.
                int             count      = 0;
                ParameterInfo[] parameters = match[i].GetParameters();
                // Go on to the next method if the number of parameters do not match.
                if (args.Length != parameters.Length)
                {
                    continue;
                }
                // Match each of the parameters that the user expects the method to have.
                for (int j = 0; j < args.Length; j++)
                {
                    // If the names parameter is not null, then reorder args.
                    if (names != null)
                    {
                        if (names.Length != args.Length)
                        {
                            throw new ArgumentException("names and args must have the same number of elements.");
                        }
                        for (int k = 0; k < names.Length; k++)
                        {
                            if (String.Compare(parameters[j].Name, names[k].ToString()) == 0)
                            {
                                args[j] = myBinderState.args[k];
                            }
                        }
                    }
                    // Determine whether the types specified by the user can be converted to the parameter type.
                    if (ChangeType(args[j], parameters[j].ParameterType, culture) != null)
                    {
                        count += 1;
                    }
                    else
                    {
                        break;
                    }
                }
                // Determine whether the method has been found.
                if (count == args.Length)
                {
                    return(match[i]);
                }
            }
            return(null);
        }
示例#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 == typeof(object))
                    {
                        continue;
                    }

                    // now do a "classic" type check
                    if (pCls.IsPrimitive)
                    {
                        if (argTypes[paramOrder[i][j]] == null || !CanChangePrimitiveObjectToType(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 || !CanChangePrimitiveObjectToType(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]);
        }
示例#5
0
        public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] canidates, ref object[] args, ParameterModifier[] modifiers, CultureInfo cultureInfo, string[] names, out object state)
        {
            int num;
            int length;

            state = null;
            if ((canidates == null) || (canidates.Length == 0))
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "canidates");
            }
            int[][] numArray = new int[canidates.Length][];
            for (num = 0; num < canidates.Length; num++)
            {
                ParameterInfo[] pars = canidates[num].GetParametersNoCopy();
                numArray[num] = new int[(pars.Length > args.Length) ? pars.Length : args.Length];
                if (names == null)
                {
                    length = 0;
                    while (length < args.Length)
                    {
                        numArray[num][length] = length;
                        length++;
                    }
                }
                else if (!CreateParamOrder(numArray[num], pars, names))
                {
                    canidates[num] = null;
                }
            }
            Type[] typeArray = new Type[canidates.Length];
            Type[] types     = new Type[args.Length];
            for (num = 0; num < args.Length; num++)
            {
                if (args[num] != null)
                {
                    types[num] = args[num].GetType();
                }
            }
            int  index       = 0;
            bool flag        = (bindingAttr & BindingFlags.OptionalParamBinding) != BindingFlags.Default;
            Type elementType = null;

            for (num = 0; num < canidates.Length; num++)
            {
                elementType = null;
                if (canidates[num] != null)
                {
                    ParameterInfo[] infoArray2 = canidates[num].GetParametersNoCopy();
                    if (infoArray2.Length == 0)
                    {
                        if ((args.Length == 0) || ((canidates[num].CallingConvention & CallingConventions.VarArgs) != 0))
                        {
                            numArray[index]    = numArray[num];
                            canidates[index++] = canidates[num];
                        }
                        continue;
                    }
                    if (infoArray2.Length > args.Length)
                    {
                        length = args.Length;
                        while (length < (infoArray2.Length - 1))
                        {
                            if (infoArray2[length].DefaultValue == DBNull.Value)
                            {
                                break;
                            }
                            length++;
                        }
                        if (length != (infoArray2.Length - 1))
                        {
                            continue;
                        }
                        if (infoArray2[length].DefaultValue == DBNull.Value)
                        {
                            if (!infoArray2[length].ParameterType.IsArray || !infoArray2[length].IsDefined(typeof(ParamArrayAttribute), true))
                            {
                                continue;
                            }
                            elementType = infoArray2[length].ParameterType.GetElementType();
                        }
                    }
                    else if (infoArray2.Length < args.Length)
                    {
                        int num4 = infoArray2.Length - 1;
                        if ((!infoArray2[num4].ParameterType.IsArray || !infoArray2[num4].IsDefined(typeof(ParamArrayAttribute), true)) || (numArray[num][num4] != num4))
                        {
                            continue;
                        }
                        elementType = infoArray2[num4].ParameterType.GetElementType();
                    }
                    else
                    {
                        int num5 = infoArray2.Length - 1;
                        if ((infoArray2[num5].ParameterType.IsArray && infoArray2[num5].IsDefined(typeof(ParamArrayAttribute), true)) && ((numArray[num][num5] == num5) && !infoArray2[num5].ParameterType.IsAssignableFrom(types[num5])))
                        {
                            elementType = infoArray2[num5].ParameterType.GetElementType();
                        }
                    }
                    Type parameterType = null;
                    int  num6          = (elementType != null) ? (infoArray2.Length - 1) : args.Length;
                    length = 0;
                    while (length < num6)
                    {
                        parameterType = infoArray2[length].ParameterType;
                        if (parameterType.IsByRef)
                        {
                            parameterType = parameterType.GetElementType();
                        }
                        if (((parameterType != types[numArray[num][length]]) && (!flag || (args[numArray[num][length]] != Type.Missing))) && ((args[numArray[num][length]] != null) && (parameterType != typeof(object))))
                        {
                            if (parameterType.IsPrimitive)
                            {
                                if ((types[numArray[num][length]] == null) || !CanConvertPrimitiveObjectToType(args[numArray[num][length]], (RuntimeType)parameterType))
                                {
                                    break;
                                }
                            }
                            else if (((types[numArray[num][length]] != null) && !parameterType.IsAssignableFrom(types[numArray[num][length]])) && (!types[numArray[num][length]].IsCOMObject || !parameterType.IsInstanceOfType(args[numArray[num][length]])))
                            {
                                break;
                            }
                        }
                        length++;
                    }
                    if ((elementType != null) && (length == (infoArray2.Length - 1)))
                    {
                        while (length < args.Length)
                        {
                            if (elementType.IsPrimitive)
                            {
                                if ((types[length] == null) || !CanConvertPrimitiveObjectToType(args[length], (RuntimeType)elementType))
                                {
                                    break;
                                }
                            }
                            else if (((types[length] != null) && !elementType.IsAssignableFrom(types[length])) && (!types[length].IsCOMObject || !elementType.IsInstanceOfType(args[length])))
                            {
                                break;
                            }
                            length++;
                        }
                    }
                    if (length == args.Length)
                    {
                        numArray[index]    = numArray[num];
                        typeArray[index]   = elementType;
                        canidates[index++] = canidates[num];
                    }
                }
            }
            switch (index)
            {
            case 0:
                throw new MissingMethodException(Environment.GetResourceString("MissingMember"));

            case 1:
            {
                if (names != null)
                {
                    state = new BinderState((int[])numArray[0].Clone(), args.Length, typeArray[0] != null);
                    ReorderParams(numArray[0], args);
                }
                ParameterInfo[] infoArray3 = canidates[0].GetParametersNoCopy();
                if (infoArray3.Length == args.Length)
                {
                    if (typeArray[0] != null)
                    {
                        object[] destinationArray = new object[infoArray3.Length];
                        int      num7             = infoArray3.Length - 1;
                        Array.Copy(args, 0, destinationArray, 0, num7);
                        destinationArray[num7] = Array.CreateInstance(typeArray[0], 1);
                        ((Array)destinationArray[num7]).SetValue(args[num7], 0);
                        args = destinationArray;
                    }
                }
                else if (infoArray3.Length > args.Length)
                {
                    object[] objArray2 = new object[infoArray3.Length];
                    num = 0;
                    while (num < args.Length)
                    {
                        objArray2[num] = args[num];
                        num++;
                    }
                    while (num < (infoArray3.Length - 1))
                    {
                        objArray2[num] = infoArray3[num].DefaultValue;
                        num++;
                    }
                    if (typeArray[0] != null)
                    {
                        objArray2[num] = Array.CreateInstance(typeArray[0], 0);
                    }
                    else
                    {
                        objArray2[num] = infoArray3[num].DefaultValue;
                    }
                    args = objArray2;
                }
                else if ((canidates[0].CallingConvention & CallingConventions.VarArgs) == 0)
                {
                    object[] objArray3 = new object[infoArray3.Length];
                    int      num8      = infoArray3.Length - 1;
                    Array.Copy(args, 0, objArray3, 0, num8);
                    objArray3[num8] = Array.CreateInstance(typeArray[0], (int)(args.Length - num8));
                    Array.Copy(args, num8, (Array)objArray3[num8], 0, args.Length - num8);
                    args = objArray3;
                }
                return(canidates[0]);
            }
            }
            int  num9  = 0;
            bool flag2 = false;

            for (num = 1; num < index; num++)
            {
                switch (FindMostSpecificMethod(canidates[num9], numArray[num9], typeArray[num9], canidates[num], numArray[num], typeArray[num], types, args))
                {
                case 0:
                    flag2 = true;
                    break;

                case 2:
                    num9  = num;
                    flag2 = false;
                    break;
                }
            }
            if (flag2)
            {
                throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.Ambiguous"));
            }
            if (names != null)
            {
                state = new BinderState((int[])numArray[num9].Clone(), args.Length, typeArray[num9] != null);
                ReorderParams(numArray[num9], args);
            }
            ParameterInfo[] parametersNoCopy = canidates[num9].GetParametersNoCopy();
            if (parametersNoCopy.Length == args.Length)
            {
                if (typeArray[num9] != null)
                {
                    object[] objArray4 = new object[parametersNoCopy.Length];
                    int      num11     = parametersNoCopy.Length - 1;
                    Array.Copy(args, 0, objArray4, 0, num11);
                    objArray4[num11] = Array.CreateInstance(typeArray[num9], 1);
                    ((Array)objArray4[num11]).SetValue(args[num11], 0);
                    args = objArray4;
                }
            }
            else if (parametersNoCopy.Length > args.Length)
            {
                object[] objArray5 = new object[parametersNoCopy.Length];
                num = 0;
                while (num < args.Length)
                {
                    objArray5[num] = args[num];
                    num++;
                }
                while (num < (parametersNoCopy.Length - 1))
                {
                    objArray5[num] = parametersNoCopy[num].DefaultValue;
                    num++;
                }
                if (typeArray[num9] != null)
                {
                    objArray5[num] = Array.CreateInstance(typeArray[num9], 0);
                }
                else
                {
                    objArray5[num] = parametersNoCopy[num].DefaultValue;
                }
                args = objArray5;
            }
            else if ((canidates[num9].CallingConvention & CallingConventions.VarArgs) == 0)
            {
                object[] objArray6 = new object[parametersNoCopy.Length];
                int      num12     = parametersNoCopy.Length - 1;
                Array.Copy(args, 0, objArray6, 0, num12);
                objArray6[num] = Array.CreateInstance(typeArray[num9], (int)(args.Length - num12));
                Array.Copy(args, num12, (Array)objArray6[num], 0, args.Length - num12);
                args = objArray6;
            }
            return(canidates[num9]);
        }
示例#6
0
 public ValveParameters(IEnumerable <CandidateProperty> properties, BinderState relativeProperties)
 {
     Properties    = properties;
     ExternalState = relativeProperties;
 }
        public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo cultureInfo, string[] names, out object state)
        {
            int num;
            int length;
            if ((match == null) || (match.Length == 0))
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match");
            }
            MethodBase[] baseArray = (MethodBase[]) match.Clone();
            state = null;
            int[][] numArray = new int[baseArray.Length][];
            for (num = 0; num < baseArray.Length; num++)
            {
                ParameterInfo[] pars = baseArray[num].GetParametersNoCopy();
                numArray[num] = new int[(pars.Length > args.Length) ? pars.Length : args.Length];
                if (names == null)
                {
                    length = 0;
                    while (length < args.Length)
                    {
                        numArray[num][length] = length;
                        length++;
                    }
                }
                else if (!CreateParamOrder(numArray[num], pars, names))
                {
                    baseArray[num] = null;
                }
            }
            Type[] typeArray = new Type[baseArray.Length];
            Type[] types = new Type[args.Length];
            for (num = 0; num < args.Length; num++)
            {
                if (args[num] != null)
                {
                    types[num] = args[num].GetType();
                }
            }
            int index = 0;
            bool flag = (bindingAttr & BindingFlags.OptionalParamBinding) != BindingFlags.Default;
            Type elementType = null;
            for (num = 0; num < baseArray.Length; num++)
            {
                elementType = null;
                if (baseArray[num] != null)
                {
                    ParameterInfo[] infoArray2 = baseArray[num].GetParametersNoCopy();
                    if (infoArray2.Length == 0)
                    {
                        if ((args.Length == 0) || ((baseArray[num].CallingConvention & CallingConventions.VarArgs) != 0))
                        {
                            numArray[index] = numArray[num];
                            baseArray[index++] = baseArray[num];
                        }
                        continue;
                    }
                    if (infoArray2.Length > args.Length)
                    {
                        length = args.Length;
                        while (length < (infoArray2.Length - 1))
                        {
                            if (infoArray2[length].DefaultValue == DBNull.Value)
                            {
                                break;
                            }
                            length++;
                        }
                        if (length != (infoArray2.Length - 1))
                        {
                            continue;
                        }
                        if (infoArray2[length].DefaultValue == DBNull.Value)
                        {
                            if (!infoArray2[length].ParameterType.IsArray || !infoArray2[length].IsDefined(typeof(ParamArrayAttribute), true))
                            {
                                continue;
                            }
                            elementType = infoArray2[length].ParameterType.GetElementType();
                        }
                    }
                    else if (infoArray2.Length < args.Length)
                    {
                        int num4 = infoArray2.Length - 1;
                        if ((!infoArray2[num4].ParameterType.IsArray || !infoArray2[num4].IsDefined(typeof(ParamArrayAttribute), true)) || (numArray[num][num4] != num4))
                        {
                            continue;
                        }
                        elementType = infoArray2[num4].ParameterType.GetElementType();
                    }
                    else
                    {
                        int num5 = infoArray2.Length - 1;
                        if ((infoArray2[num5].ParameterType.IsArray && infoArray2[num5].IsDefined(typeof(ParamArrayAttribute), true)) && ((numArray[num][num5] == num5) && !infoArray2[num5].ParameterType.IsAssignableFrom(types[num5])))
                        {
                            elementType = infoArray2[num5].ParameterType.GetElementType();
                        }
                    }
                    Type parameterType = null;
                    int num6 = (elementType != null) ? (infoArray2.Length - 1) : args.Length;
                    length = 0;
                    while (length < num6)
                    {
                        parameterType = infoArray2[length].ParameterType;
                        if (parameterType.IsByRef)
                        {
                            parameterType = parameterType.GetElementType();
                        }
                        if (((parameterType != types[numArray[num][length]]) && (!flag || (args[numArray[num][length]] != Type.Missing))) && ((args[numArray[num][length]] != null) && (parameterType != typeof(object))))
                        {
                            if (parameterType.IsPrimitive)
                            {
                                if ((types[numArray[num][length]] == null) || !CanConvertPrimitiveObjectToType(args[numArray[num][length]], (RuntimeType) parameterType))
                                {
                                    break;
                                }
                            }
                            else if (((types[numArray[num][length]] != null) && !parameterType.IsAssignableFrom(types[numArray[num][length]])) && (!types[numArray[num][length]].IsCOMObject || !parameterType.IsInstanceOfType(args[numArray[num][length]])))
                            {
                                break;
                            }
                        }
                        length++;
                    }
                    if ((elementType != null) && (length == (infoArray2.Length - 1)))
                    {
                        while (length < args.Length)
                        {
                            if (elementType.IsPrimitive)
                            {
                                if ((types[length] == null) || !CanConvertPrimitiveObjectToType(args[length], (RuntimeType) elementType))
                                {
                                    break;
                                }
                            }
                            else if (((types[length] != null) && !elementType.IsAssignableFrom(types[length])) && (!types[length].IsCOMObject || !elementType.IsInstanceOfType(args[length])))
                            {
                                break;
                            }
                            length++;
                        }
                    }
                    if (length == args.Length)
                    {
                        numArray[index] = numArray[num];
                        typeArray[index] = elementType;
                        baseArray[index++] = baseArray[num];
                    }
                }
            }
            switch (index)
            {
                case 0:
                    throw new MissingMethodException(Environment.GetResourceString("MissingMember"));

                case 1:
                {
                    if (names != null)
                    {
                        state = new BinderState((int[]) numArray[0].Clone(), args.Length, typeArray[0] != null);
                        ReorderParams(numArray[0], args);
                    }
                    ParameterInfo[] infoArray3 = baseArray[0].GetParametersNoCopy();
                    if (infoArray3.Length == args.Length)
                    {
                        if (typeArray[0] != null)
                        {
                            object[] destinationArray = new object[infoArray3.Length];
                            int num7 = infoArray3.Length - 1;
                            Array.Copy(args, 0, destinationArray, 0, num7);
                            destinationArray[num7] = Array.UnsafeCreateInstance(typeArray[0], 1);
                            ((Array) destinationArray[num7]).SetValue(args[num7], 0);
                            args = destinationArray;
                        }
                    }
                    else if (infoArray3.Length > args.Length)
                    {
                        object[] objArray2 = new object[infoArray3.Length];
                        num = 0;
                        while (num < args.Length)
                        {
                            objArray2[num] = args[num];
                            num++;
                        }
                        while (num < (infoArray3.Length - 1))
                        {
                            objArray2[num] = infoArray3[num].DefaultValue;
                            num++;
                        }
                        if (typeArray[0] != null)
                        {
                            objArray2[num] = Array.UnsafeCreateInstance(typeArray[0], 0);
                        }
                        else
                        {
                            objArray2[num] = infoArray3[num].DefaultValue;
                        }
                        args = objArray2;
                    }
                    else if ((baseArray[0].CallingConvention & CallingConventions.VarArgs) == 0)
                    {
                        object[] objArray3 = new object[infoArray3.Length];
                        int num8 = infoArray3.Length - 1;
                        Array.Copy(args, 0, objArray3, 0, num8);
                        objArray3[num8] = Array.UnsafeCreateInstance(typeArray[0], (int) (args.Length - num8));
                        Array.Copy(args, num8, (Array) objArray3[num8], 0, args.Length - num8);
                        args = objArray3;
                    }
                    return baseArray[0];
                }
            }
            int num9 = 0;
            bool flag2 = false;
            for (num = 1; num < index; num++)
            {
                switch (FindMostSpecificMethod(baseArray[num9], numArray[num9], typeArray[num9], baseArray[num], numArray[num], typeArray[num], types, args))
                {
                    case 0:
                        flag2 = true;
                        break;

                    case 2:
                        num9 = num;
                        flag2 = false;
                        break;
                }
            }
            if (flag2)
            {
                throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
            }
            if (names != null)
            {
                state = new BinderState((int[]) numArray[num9].Clone(), args.Length, typeArray[num9] != null);
                ReorderParams(numArray[num9], args);
            }
            ParameterInfo[] parametersNoCopy = baseArray[num9].GetParametersNoCopy();
            if (parametersNoCopy.Length == args.Length)
            {
                if (typeArray[num9] != null)
                {
                    object[] objArray4 = new object[parametersNoCopy.Length];
                    int num11 = parametersNoCopy.Length - 1;
                    Array.Copy(args, 0, objArray4, 0, num11);
                    objArray4[num11] = Array.UnsafeCreateInstance(typeArray[num9], 1);
                    ((Array) objArray4[num11]).SetValue(args[num11], 0);
                    args = objArray4;
                }
            }
            else if (parametersNoCopy.Length > args.Length)
            {
                object[] objArray5 = new object[parametersNoCopy.Length];
                num = 0;
                while (num < args.Length)
                {
                    objArray5[num] = args[num];
                    num++;
                }
                while (num < (parametersNoCopy.Length - 1))
                {
                    objArray5[num] = parametersNoCopy[num].DefaultValue;
                    num++;
                }
                if (typeArray[num9] != null)
                {
                    objArray5[num] = Array.UnsafeCreateInstance(typeArray[num9], 0);
                }
                else
                {
                    objArray5[num] = parametersNoCopy[num].DefaultValue;
                }
                args = objArray5;
            }
            else if ((baseArray[num9].CallingConvention & CallingConventions.VarArgs) == 0)
            {
                object[] objArray6 = new object[parametersNoCopy.Length];
                int num12 = parametersNoCopy.Length - 1;
                Array.Copy(args, 0, objArray6, 0, num12);
                objArray6[num12] = Array.UnsafeCreateInstance(typeArray[num9], (int) (args.Length - num12));
                Array.Copy(args, num12, (Array) objArray6[num12], 0, args.Length - num12);
                args = objArray6;
            }
            return baseArray[num9];
        }