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;
for (int i = 0; i < array.Length; i++)
{
Type 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_426;
}
if (parametersNoCopy2[j].DefaultValue == DBNull.Value)
{
if (!parametersNoCopy2[j].ParameterType.IsArray || !parametersNoCopy2[j].IsDefined(typeof(ParamArrayAttribute), true))
{
goto IL_426;
}
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_426;
}
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();
}
}
int num4 = (type != null) ? (parametersNoCopy2.Length - 1) : args.Length;
for (j = 0; j < num4; j++)
{
Type 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_426 :;
}
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]);
}