in src/Shared/Compat/defaultbinder.cs [615:722]
public override PropertyInfo SelectProperty(BindingFlags bindingAttr,PropertyInfo[] match,Type returnType,
Type[] indexes,ParameterModifier[] modifiers)
{
// Allow a null indexes array. But if it is not null, every element must be non-null as well.
if (indexes != null && !Contract.ForAll(indexes, delegate(Type t) { return t != null; }))
{
Exception e; // Written this way to pass the Code Contracts style requirements.
#if FEATURE_LEGACYNETCF
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
e = new NullReferenceException();
else
#endif
e = new ArgumentNullException("indexes");
throw e;
}
if (match == null || match.Length == 0)
throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match");
Contract.EndContractBlock();
PropertyInfo[] candidates = (PropertyInfo[]) match.Clone();
int i,j = 0;
// Find all the properties that can be described by type indexes parameter
int CurIdx = 0;
int indexesLength = (indexes != null) ? indexes.Length : 0;
for (i=0;i<candidates.Length;i++) {
if (indexes != null)
{
ParameterInfo[] par = candidates[i].GetIndexParameters();
if (par.Length != indexesLength)
continue;
for (j=0;j<indexesLength;j++) {
Type pCls = par[j]. ParameterType;
// If the classes exactly match continue
if (pCls == indexes[j])
continue;
if (pCls == typeof(Object))
continue;
if (pCls.IsPrimitive) {
if (!(indexes[j].UnderlyingSystemType is RuntimeType) ||
!CanConvertPrimitive((RuntimeType)indexes[j].UnderlyingSystemType,(RuntimeType)pCls.UnderlyingSystemType))
break;
}
else {
if (!pCls.IsAssignableFrom(indexes[j]))
break;
}
}
}
if (j == indexesLength) {
if (returnType != null) {
if (candidates[i].PropertyType.IsPrimitive) {
if (!(returnType.UnderlyingSystemType is RuntimeType) ||
!CanConvertPrimitive((RuntimeType)returnType.UnderlyingSystemType,(RuntimeType)candidates[i].PropertyType.UnderlyingSystemType))
continue;
}
else {
if (!candidates[i].PropertyType.IsAssignableFrom(returnType))
continue;
}
}
candidates[CurIdx++] = candidates[i];
}
}
if (CurIdx == 0)
return null;
if (CurIdx == 1)
return candidates[0];
// Walk all of the properties looking the most specific method to invoke
int currentMin = 0;
bool ambig = false;
int[] paramOrder = new int[indexesLength];
for (i=0;i<indexesLength;i++)
paramOrder[i] = i;
for (i=1;i<CurIdx;i++) {
int newMin = FindMostSpecificType(candidates[currentMin].PropertyType, candidates[i].PropertyType,returnType);
if (newMin == 0 && indexes != null)
newMin = FindMostSpecific(candidates[currentMin].GetIndexParameters(),
paramOrder,
null,
candidates[i].GetIndexParameters(),
paramOrder,
null,
indexes,
null);
if (newMin == 0)
{
newMin = FindMostSpecificProperty(candidates[currentMin], candidates[i]);
if (newMin == 0)
ambig = true;
}
if (newMin == 2) {
ambig = false;
currentMin = i;
}
}
if (ambig)
throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
return candidates[currentMin];
}