[System.Security.SecuritySafeCritical] // auto-generated public 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] is RuntimeType)) throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"types"); } types = realTypes; // We don't automatically jump out on exact match. if (match == null || match.Length == 0) throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "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 == typeof(Object)) continue; if (pCls.IsPrimitive) { if (!(types[j].UnderlyingSystemType is RuntimeType) || !CanConvertPrimitive((RuntimeType)types[j].UnderlyingSystemType,(RuntimeType)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(Environment.GetResourceString("Arg_AmbiguousMatchException")); return candidates[currentMin]; }
// 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]; }
[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]; }
// 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"); } 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]; }
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]; }
public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers) { int num; Type[] typeArray = new Type[types.Length]; for (num = 0; num < types.Length; num++) { typeArray[num] = types[num].UnderlyingSystemType; if (!(typeArray[num] is RuntimeType)) { throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "types"); } } types = typeArray; if ((match == null) || (match.Length == 0)) { throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match"); } MethodBase[] baseArray = (MethodBase[]) match.Clone(); int num3 = 0; for (num = 0; num < baseArray.Length; num++) { ParameterInfo[] parametersNoCopy = baseArray[num].GetParametersNoCopy(); if (parametersNoCopy.Length == types.Length) { int num2 = 0; while (num2 < types.Length) { Type parameterType = parametersNoCopy[num2].ParameterType; if ((parameterType != types[num2]) && (parameterType != typeof(object))) { if (parameterType.IsPrimitive) { if (!(types[num2].UnderlyingSystemType is RuntimeType) || !CanConvertPrimitive((RuntimeType) types[num2].UnderlyingSystemType, (RuntimeType) parameterType.UnderlyingSystemType)) { break; } } else if (!parameterType.IsAssignableFrom(types[num2])) { break; } } num2++; } if (num2 == types.Length) { baseArray[num3++] = baseArray[num]; } } } switch (num3) { case 0: return null; case 1: return baseArray[0]; } int index = 0; bool flag = false; int[] numArray = new int[types.Length]; for (num = 0; num < types.Length; num++) { numArray[num] = num; } for (num = 1; num < num3; num++) { switch (FindMostSpecificMethod(baseArray[index], numArray, null, baseArray[num], numArray, null, types, null)) { case 0: flag = true; break; case 2: index = num; flag = false; index = num; break; } } if (flag) { throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); } return baseArray[index]; }
public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers) { Type[] array = new Type[types.Length]; for (int i = 0; i < types.Length; i++) { array[i] = types[i].UnderlyingSystemType; if (!(array[i] is RuntimeType)) { throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "types"); } } types = array; if (match == null || match.Length == 0) { throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match"); } MethodBase[] array2 = (MethodBase[])match.Clone(); int num = 0; for (int i = 0; i < array2.Length; i++) { ParameterInfo[] parametersNoCopy = array2[i].GetParametersNoCopy(); if (parametersNoCopy.Length == types.Length) { int j; for (j = 0; j < types.Length; j++) { Type parameterType = parametersNoCopy[j].ParameterType; if (!(parameterType == types[j]) && !(parameterType == typeof(object))) { if (parameterType.IsPrimitive) { if (!(types[j].UnderlyingSystemType is RuntimeType)) { break; } if (!DefaultBinder.CanConvertPrimitive((RuntimeType)types[j].UnderlyingSystemType, (RuntimeType)parameterType.UnderlyingSystemType)) { break; } } else { if (!parameterType.IsAssignableFrom(types[j])) { break; } } } } if (j == types.Length) { array2[num++] = array2[i]; } } } if (num == 0) { return null; } if (num == 1) { return array2[0]; } int num2 = 0; bool flag = false; int[] array3 = new int[types.Length]; for (int i = 0; i < types.Length; i++) { array3[i] = i; } for (int i = 1; i < num; i++) { int num3 = DefaultBinder.FindMostSpecificMethod(array2[num2], array3, null, array2[i], array3, null, types, null); if (num3 == 0) { flag = true; } else { if (num3 == 2) { num2 = i; flag = false; num2 = i; } } } if (flag) { throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); } return array2[num2]; }
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"); } MethodBase[] array = (MethodBase[])match.Clone(); state = null; int[][] array2 = new int[array.Length][]; for (int i = 0; i < array.Length; i++) { ParameterInfo[] parametersNoCopy = array[i].GetParametersNoCopy(); array2[i] = new int[(parametersNoCopy.Length > args.Length) ? parametersNoCopy.Length : args.Length]; if (names == null) { for (int j = 0; j < args.Length; j++) { array2[i][j] = j; } } else { if (!DefaultBinder.CreateParamOrder(array2[i], parametersNoCopy, names)) { array[i] = null; } } } Type[] array3 = new Type[array.Length]; Type[] array4 = new Type[args.Length]; for (int i = 0; i < args.Length; i++) { if (args[i] != null) { array4[i] = args[i].GetType(); } } int num = 0; bool flag = (bindingAttr & BindingFlags.OptionalParamBinding) != BindingFlags.Default; Type type = null; for (int i = 0; i < array.Length; i++) { type = null; if (!(array[i] == null)) { ParameterInfo[] parametersNoCopy2 = array[i].GetParametersNoCopy(); if (parametersNoCopy2.Length == 0) { if (args.Length == 0 || (array[i].CallingConvention & CallingConventions.VarArgs) != (CallingConventions)0) { array2[num] = array2[i]; array[num++] = array[i]; } } else { int j; if (parametersNoCopy2.Length > args.Length) { j = args.Length; while (j < parametersNoCopy2.Length - 1 && parametersNoCopy2[j].DefaultValue != DBNull.Value) { j++; } if (j != parametersNoCopy2.Length - 1) { goto IL_42C; } if (parametersNoCopy2[j].DefaultValue == DBNull.Value) { if (!parametersNoCopy2[j].ParameterType.IsArray || !parametersNoCopy2[j].IsDefined(typeof(ParamArrayAttribute), true)) { goto IL_42C; } type = parametersNoCopy2[j].ParameterType.GetElementType(); } } else { if (parametersNoCopy2.Length < args.Length) { int num2 = parametersNoCopy2.Length - 1; if (!parametersNoCopy2[num2].ParameterType.IsArray || !parametersNoCopy2[num2].IsDefined(typeof(ParamArrayAttribute), true) || array2[i][num2] != num2) { goto IL_42C; } type = parametersNoCopy2[num2].ParameterType.GetElementType(); } else { int num3 = parametersNoCopy2.Length - 1; if (parametersNoCopy2[num3].ParameterType.IsArray && parametersNoCopy2[num3].IsDefined(typeof(ParamArrayAttribute), true) && array2[i][num3] == num3 && !parametersNoCopy2[num3].ParameterType.IsAssignableFrom(array4[num3])) { type = parametersNoCopy2[num3].ParameterType.GetElementType(); } } } Type type2 = null; int num4 = (type != null) ? (parametersNoCopy2.Length - 1) : args.Length; for (j = 0; j < num4; j++) { type2 = parametersNoCopy2[j].ParameterType; if (type2.IsByRef) { type2 = type2.GetElementType(); } if (!(type2 == array4[array2[i][j]]) && (!flag || args[array2[i][j]] != Type.Missing) && args[array2[i][j]] != null && !(type2 == typeof(object))) { if (type2.IsPrimitive) { if (array4[array2[i][j]] == null) { break; } if (!DefaultBinder.CanConvertPrimitiveObjectToType(args[array2[i][j]], (RuntimeType)type2)) { break; } } else { if (!(array4[array2[i][j]] == null) && !type2.IsAssignableFrom(array4[array2[i][j]]) && (!array4[array2[i][j]].IsCOMObject || !type2.IsInstanceOfType(args[array2[i][j]]))) { break; } } } } if (type != null && j == parametersNoCopy2.Length - 1) { while (j < args.Length) { if (type.IsPrimitive) { if (array4[j] == null) { break; } if (!DefaultBinder.CanConvertPrimitiveObjectToType(args[j], (RuntimeType)type)) { break; } } else { if (!(array4[j] == null) && !type.IsAssignableFrom(array4[j]) && (!array4[j].IsCOMObject || !type.IsInstanceOfType(args[j]))) { break; } } j++; } } if (j == args.Length) { array2[num] = array2[i]; array3[num] = type; array[num++] = array[i]; } } } IL_42C:; } if (num == 0) { throw new MissingMethodException(Environment.GetResourceString("MissingMember")); } if (num == 1) { if (names != null) { state = new DefaultBinder.BinderState((int[])array2[0].Clone(), args.Length, array3[0] != null); DefaultBinder.ReorderParams(array2[0], args); } ParameterInfo[] parametersNoCopy3 = array[0].GetParametersNoCopy(); if (parametersNoCopy3.Length == args.Length) { if (array3[0] != null) { object[] array5 = new object[parametersNoCopy3.Length]; int num5 = parametersNoCopy3.Length - 1; Array.Copy(args, 0, array5, 0, num5); array5[num5] = Array.UnsafeCreateInstance(array3[0], 1); ((Array)array5[num5]).SetValue(args[num5], 0); args = array5; } } else { if (parametersNoCopy3.Length > args.Length) { object[] array6 = new object[parametersNoCopy3.Length]; int i; for (i = 0; i < args.Length; i++) { array6[i] = args[i]; } while (i < parametersNoCopy3.Length - 1) { array6[i] = parametersNoCopy3[i].DefaultValue; i++; } if (array3[0] != null) { array6[i] = Array.UnsafeCreateInstance(array3[0], 0); } else { array6[i] = parametersNoCopy3[i].DefaultValue; } args = array6; } else { if ((array[0].CallingConvention & CallingConventions.VarArgs) == (CallingConventions)0) { object[] array7 = new object[parametersNoCopy3.Length]; int num6 = parametersNoCopy3.Length - 1; Array.Copy(args, 0, array7, 0, num6); array7[num6] = Array.UnsafeCreateInstance(array3[0], args.Length - num6); Array.Copy(args, num6, (Array)array7[num6], 0, args.Length - num6); args = array7; } } } return array[0]; } int num7 = 0; bool flag2 = false; for (int i = 1; i < num; i++) { int num8 = DefaultBinder.FindMostSpecificMethod(array[num7], array2[num7], array3[num7], array[i], array2[i], array3[i], array4, args); if (num8 == 0) { flag2 = true; } else { if (num8 == 2) { num7 = i; flag2 = false; } } } if (flag2) { throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); } if (names != null) { state = new DefaultBinder.BinderState((int[])array2[num7].Clone(), args.Length, array3[num7] != null); DefaultBinder.ReorderParams(array2[num7], args); } ParameterInfo[] parametersNoCopy4 = array[num7].GetParametersNoCopy(); if (parametersNoCopy4.Length == args.Length) { if (array3[num7] != null) { object[] array8 = new object[parametersNoCopy4.Length]; int num9 = parametersNoCopy4.Length - 1; Array.Copy(args, 0, array8, 0, num9); array8[num9] = Array.UnsafeCreateInstance(array3[num7], 1); ((Array)array8[num9]).SetValue(args[num9], 0); args = array8; } } else { if (parametersNoCopy4.Length > args.Length) { object[] array9 = new object[parametersNoCopy4.Length]; int i; for (i = 0; i < args.Length; i++) { array9[i] = args[i]; } while (i < parametersNoCopy4.Length - 1) { array9[i] = parametersNoCopy4[i].DefaultValue; i++; } if (array3[num7] != null) { array9[i] = Array.UnsafeCreateInstance(array3[num7], 0); } else { array9[i] = parametersNoCopy4[i].DefaultValue; } args = array9; } else { if ((array[num7].CallingConvention & CallingConventions.VarArgs) == (CallingConventions)0) { object[] array10 = new object[parametersNoCopy4.Length]; int num10 = parametersNoCopy4.Length - 1; Array.Copy(args, 0, array10, 0, num10); array10[num10] = Array.UnsafeCreateInstance(array3[num7], args.Length - num10); Array.Copy(args, num10, (Array)array10[num10], 0, args.Length - num10); args = array10; } } } return array[num7]; }