public override PropertyInfo SelectProperty()

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];
        }