private MethodInfo FindBestMethod(MethodInfo[] methods, bool ignoreCase, bool publicOnly, string name, XPathResultType[] argTypes) {
int length = methods.Length;
int free = 0;
// restrict search to methods with the same name and requiested protection attribute
for(int i = 0; i < length; i ++) {
if(string.Compare(name, methods[i].Name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) == 0) {
if(! publicOnly || methods[i].GetBaseDefinition().IsPublic) {
methods[free ++] = methods[i];
}
}
}
length = free;
if(length == 0) {
// this is the only place we returning null in this function
return null;
}
if(argTypes == null) {
// without arg types we can't do more detailed search
return methods[0];
}
// restrict search by number of parameters
free = 0;
for(int i = 0; i < length; i ++) {
if(methods[i].GetParameters().Length == argTypes.Length) {
methods[free ++] = methods[i];
}
}
length = free;
if(length <= 1) {
// 0 -- not method found. We have to return non-null and let it fail with corect exception on call.
// 1 -- no reason to continue search anyway.
return methods[0];
}
// restrict search by parameters type
free = 0;
for(int i = 0; i < length; i ++) {
bool match = true;
ParameterInfo[] parameters = methods[i].GetParameters();
for(int par = 0; par < parameters.Length; par ++) {
XPathResultType required = argTypes[par];
if(required == XPathResultType.Any) {
continue; // Any means we don't know type and can't discriminate by it
}
XPathResultType actual = GetXPathType(parameters[par].ParameterType);
if(
actual != required &&
actual != XPathResultType.Any // actual arg is object and we can pass everithing here.
) {
match = false;
break;
}
}
if(match) {
methods[free ++] = methods[i];
}
}
length = free;
return methods[0];
}