in src/Shared/Compat/TypeExtensions.cs [514:642]
private static bool FilterApplyMethodBase(
MethodBase methodBase, BindingFlags methodFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
{
Contract.Requires(methodBase != null);
bindingFlags ^= BindingFlags.DeclaredOnly;
#region Apply Base Filter
if ((bindingFlags & methodFlags) != methodFlags)
return false;
#endregion
#region Check CallingConvention
if ((callConv & CallingConventions.Any) == 0)
{
if ((callConv & CallingConventions.VarArgs) != 0 &&
(methodBase.CallingConvention & CallingConventions.VarArgs) == 0)
return false;
if ((callConv & CallingConventions.Standard) != 0 &&
(methodBase.CallingConvention & CallingConventions.Standard) == 0)
return false;
}
#endregion
#region If argumentTypes supplied
if (argumentTypes != null)
{
ParameterInfo[] parameterInfos = methodBase.GetParameters();
if (argumentTypes.Length != parameterInfos.Length)
{
#region Invoke Member, Get\Set & Create Instance specific case
//// If the number of supplied arguments differs than the number in the signature AND
//// we are not filtering for a dynamic call -- InvokeMethod or CreateInstance -- filter out the method.
//if ((bindingFlags &
// (BindingFlags.InvokeMethod | BindingFlags.CreateInstance | BindingFlags.GetProperty | BindingFlags.SetProperty)) == 0)
// return false;
bool testForParamArray = false;
bool excessSuppliedArguments = argumentTypes.Length > parameterInfos.Length;
if (excessSuppliedArguments)
{ // more supplied arguments than parameters, additional arguments could be vararg
#region Varargs
// If method is not vararg, additional arguments can not be passed as vararg
if ((methodBase.CallingConvention & CallingConventions.VarArgs) == 0)
{
testForParamArray = true;
}
else
{
// If Binding flags did not include varargs we would have filtered this vararg method.
// This Invariant established during callConv check.
Contract.Assert((callConv & CallingConventions.VarArgs) != 0);
}
#endregion
}
else
{// fewer supplied arguments than parameters, missing arguments could be optional
#region OptionalParamBinding
//if ((bindingFlags & BindingFlags.OptionalParamBinding) == 0)
if (true)
{
testForParamArray = true;
}
//else
//{
// // From our existing code, our policy here is that if a parameterInfo
// // is optional then all subsequent parameterInfos shall be optional.
// // Thus, iff the first parameterInfo is not optional then this MethodInfo is no longer a canidate.
// if (!parameterInfos[argumentTypes.Length].IsOptional)
// testForParamArray = true;
//}
#endregion
}
#region ParamArray
if (testForParamArray)
{
if (parameterInfos.Length == 0)
return false;
// The last argument of the signature could be a param array.
bool shortByMoreThanOneSuppliedArgument = argumentTypes.Length < parameterInfos.Length - 1;
if (shortByMoreThanOneSuppliedArgument)
return false;
ParameterInfo lastParameter = parameterInfos[parameterInfos.Length - 1];
if (!lastParameter.ParameterType.IsArray)
return false;
if (!lastParameter.IsDefined(typeof(ParamArrayAttribute), false))
return false;
}
#endregion
#endregion
}
else
{
//#region Exact Binding
//if ((bindingFlags & BindingFlags.ExactBinding) != 0)
//{
// // Legacy behavior is to ignore ExactBinding when InvokeMember is specified.
// // Why filter by InvokeMember? If the answer is we leave this to the binder then why not leave
// // all the rest of this to the binder too? Further, what other semanitc would the binder
// // use for BindingFlags.ExactBinding besides this one? Further, why not include CreateInstance
// // in this if statement? That's just InvokeMethod with a constructor, right?
// if ((bindingFlags & (BindingFlags.InvokeMethod)) == 0)
// {
// for (int i = 0; i < parameterInfos.Length; i++)
// {
// // a null argument type implies a null arg which is always a perfect match
// if ((object)argumentTypes[i] != null && !Object.ReferenceEquals(parameterInfos[i].ParameterType, argumentTypes[i]))
// return false;
// }
// }
//}
//#endregion
}
}
#endregion
return true;
}