// // If member is a virtual member that implicitly overrides a member in a base class, return the overridden member. // Otherwise, return null. // // - MethodImpls ignored. (I didn't say it made sense, this is just how the desktop api we're porting behaves.) // - Implemented interfaces ignores. (I didn't say it made sense, this is just how the desktop api we're porting behaves.) // public static M GetImplicitlyOverriddenBaseClassMember <M>(this M member) where M : MemberInfo { MemberPolicies <M> policies = MemberPolicies <M> .Default; MethodAttributes visibility; bool isStatic; bool isVirtual; bool isNewSlot; policies.GetMemberAttributes(member, out visibility, out isStatic, out isVirtual, out isNewSlot); if (isNewSlot || !isVirtual) { return(null); } String name = member.Name; TypeInfo typeInfo = member.DeclaringType.GetTypeInfo(); for (;;) { Type baseType = typeInfo.BaseType; if (baseType == null) { return(null); } typeInfo = baseType.GetTypeInfo(); foreach (M candidate in policies.GetDeclaredMembers(typeInfo)) { if (candidate.Name != name) { continue; } MethodAttributes candidateVisibility; bool isCandidateStatic; bool isCandidateVirtual; bool isCandidateNewSlot; policies.GetMemberAttributes(member, out candidateVisibility, out isCandidateStatic, out isCandidateVirtual, out isCandidateNewSlot); if (!isCandidateVirtual) { continue; } if (!policies.ImplicitlyOverrides(candidate, member)) { continue; } return(candidate); } } }
// // Take the result of Stage1Filter and filter by the BindingFlag bits. // private static IEnumerable <M> Stage2Filter <M>(Type type, String optionalNameFilter, BindingFlags bindingFlags, bool allowPrefixing) where M : MemberInfo { MemberPolicies <M> policies = MemberPolicies <M> .Default; bindingFlags = policies.ModifyBindingFlags(bindingFlags); bool ignoreCase = (bindingFlags & BindingFlags.IgnoreCase) != 0; bool declaredOnly = (bindingFlags & BindingFlags.DeclaredOnly) != 0; QueriedMemberList <M> queriedMembers = Stage1Filter <M>(type, optionalNameFilter, ignoreCase: ignoreCase, declaredOnly: declaredOnly, allowPrefixing: allowPrefixing); for (int i = 0; i < queriedMembers.Count; i++) { BindingFlags allFlagsThatMustMatch = queriedMembers.AllFlagsThatMustMatchNoCopy[i]; if ((bindingFlags & allFlagsThatMustMatch) == allFlagsThatMustMatch) { yield return(queriedMembers.MembersNoCopy[i]); } } }
/// <summary> /// Returns a single member, null or throws AmbigousMatchException, for the Type.Get*(string name,...) family of apis. /// </summary> public M?Disambiguate() { if (_queriedMembers == null) { return(null); // This is an uninitialized QueryResult<M>, which is supported and represents a 0-length list of matches. } int unfilteredCount = UnfilteredCount; M?match = null; for (int i = 0; i < unfilteredCount; i++) { if (_queriedMembers.Matches(i, _bindingAttr)) { if (match != null) { M challenger = _queriedMembers[i]; // Assuming the policy says it's ok to ignore the ambiguity, we're to resolve in favor of the member // declared by the most derived type. Since QueriedMemberLists are sorted in order of decreasing derivation, // that means we let the first match win - unless, of course, they're both the "most derived member". if (match.DeclaringType !.Equals(challenger.DeclaringType)) { throw new AmbiguousMatchException(); } MemberPolicies <M> policies = MemberPolicies <M> .Default; if (!policies.OkToIgnoreAmbiguity(match, challenger)) { throw new AmbiguousMatchException(); } } else { match = _queriedMembers[i]; } } } return(match); }
// // Filter by name and visibility from the ReflectedType. // public static QueriedMemberList <M> Create(RuntimeTypeInfo type, string filter, bool ignoreCase, bool immediateTypeOnly) { RuntimeTypeInfo reflectedType = type; MemberPolicies <M> policies = MemberPolicies <M> .Default; NameFilter nameFilter; if (filter == null) { nameFilter = null; } else if (ignoreCase) { nameFilter = new NameFilterCaseInsensitive(filter); } else { nameFilter = new NameFilterCaseSensitive(filter); } bool inBaseClass = false; QueriedMemberList <M> queriedMembers = new QueriedMemberList <M>(immediateTypeOnly); while (type != null) { int numCandidatesInDerivedTypes = queriedMembers._totalCount; foreach (M member in policies.CoreGetDeclaredMembers(type, nameFilter, reflectedType)) { policies.GetMemberAttributes(member, out MethodAttributes visibility, out bool isStatic, out bool isVirtual, out bool isNewSlot); if (inBaseClass && visibility == MethodAttributes.Private) { continue; } if (numCandidatesInDerivedTypes != 0 && policies.IsSuppressedByMoreDerivedMember(member, queriedMembers._members, startIndex: 0, endIndex: numCandidatesInDerivedTypes)) { continue; } BindingFlags allFlagsThatMustMatch = default; allFlagsThatMustMatch |= (isStatic ? BindingFlags.Static : BindingFlags.Instance); if (isStatic && inBaseClass) { allFlagsThatMustMatch |= BindingFlags.FlattenHierarchy; } allFlagsThatMustMatch |= ((visibility == MethodAttributes.Public) ? BindingFlags.Public : BindingFlags.NonPublic); queriedMembers.Add(member, allFlagsThatMustMatch); } if (!inBaseClass) { queriedMembers._declaredOnlyCount = queriedMembers._totalCount; if (immediateTypeOnly) { break; } if (policies.AlwaysTreatAsDeclaredOnly) { break; } inBaseClass = true; } type = type.BaseType.CastToRuntimeTypeInfo(); if (type != null && !type.CanBrowseWithoutMissingMetadataExceptions()) { // If we got here, one of the base classes is missing metadata. We don't want to throw a MissingMetadataException now because we may be // building a cached result for a caller who passed BindingFlags.DeclaredOnly. So we'll mark the results in a way that // it will throw a MissingMetadataException if a caller attempts to iterate past the declared-only subset. queriedMembers._typeThatBlockedBrowsing = type; queriedMembers._totalCount = queriedMembers._declaredOnlyCount; break; } } return(queriedMembers); }
// // Filter by name and visibility from the ReflectedType. // public static QueriedMemberList <M> Create(RuntimeTypeInfo type, string optionalNameFilter, bool ignoreCase) { RuntimeTypeInfo reflectedType = type; MemberPolicies <M> policies = MemberPolicies <M> .Default; NameFilter?nameFilter; if (optionalNameFilter == null) { nameFilter = null; } else if (ignoreCase) { nameFilter = new NameFilterCaseInsensitive(optionalNameFilter); } else { nameFilter = new NameFilterCaseSensitive(optionalNameFilter); } bool inBaseClass = false; QueriedMemberList <M> queriedMembers = new QueriedMemberList <M>(); while (type != null) { int numCandidatesInDerivedTypes = queriedMembers._totalCount; foreach (M member in policies.CoreGetDeclaredMembers(type, nameFilter, reflectedType)) { MethodAttributes visibility; bool isStatic; bool isVirtual; bool isNewSlot; policies.GetMemberAttributes(member, out visibility, out isStatic, out isVirtual, out isNewSlot); if (inBaseClass && visibility == MethodAttributes.Private) { continue; } if (numCandidatesInDerivedTypes != 0 && policies.IsSuppressedByMoreDerivedMember(member, queriedMembers._members, startIndex: 0, endIndex: numCandidatesInDerivedTypes)) { continue; } BindingFlags allFlagsThatMustMatch = default(BindingFlags); allFlagsThatMustMatch |= (isStatic ? BindingFlags.Static : BindingFlags.Instance); if (isStatic && inBaseClass) { allFlagsThatMustMatch |= BindingFlags.FlattenHierarchy; } allFlagsThatMustMatch |= ((visibility == MethodAttributes.Public) ? BindingFlags.Public : BindingFlags.NonPublic); queriedMembers.Add(member, allFlagsThatMustMatch); } if (!inBaseClass) { queriedMembers._declaredOnlyCount = queriedMembers._totalCount; if (policies.AlwaysTreatAsDeclaredOnly) { break; } inBaseClass = true; } type = type.BaseType.CastToRuntimeTypeInfo(); } return(queriedMembers); }
// // Filter by name and visibility from the ReflectedType. // private static QueriedMemberList <M> Stage1Filter <M>(Type type, String optionalNameFilter, bool ignoreCase, bool declaredOnly, bool allowPrefixing) where M : MemberInfo { Type reflectedType = type; MemberPolicies <M> policies = MemberPolicies <M> .Default; StringComparison comparisonType = ignoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture; bool inBaseClass = false; bool nameFilterIsPrefix = false; if (allowPrefixing && optionalNameFilter != null && optionalNameFilter.EndsWith("*", StringComparison.Ordinal)) { nameFilterIsPrefix = true; optionalNameFilter = optionalNameFilter.Substring(0, optionalNameFilter.Length - 1); } QueriedMemberList <M> queriedMembers = new QueriedMemberList <M>(); while (type != null) { int numCandidatesInDerivedTypes = queriedMembers.Count; TypeInfo typeInfo = type.GetTypeInfo(); foreach (M member in policies.GetDeclaredMembers(typeInfo)) { if (optionalNameFilter != null) { if (nameFilterIsPrefix) { if (!member.Name.StartsWith(optionalNameFilter, comparisonType)) { continue; } } else if (!member.Name.Equals(optionalNameFilter, comparisonType)) { continue; } } MethodAttributes visibility; bool isStatic; bool isVirtual; bool isNewSlot; policies.GetMemberAttributes(member, out visibility, out isStatic, out isVirtual, out isNewSlot); if (inBaseClass && visibility == MethodAttributes.Private) { continue; } if (numCandidatesInDerivedTypes != 0 && policies.IsSuppressedByMoreDerivedMember(member, queriedMembers.MembersNoCopy, startIndex: 0, endIndex: numCandidatesInDerivedTypes)) { continue; } BindingFlags allFlagsThatMustMatch = (BindingFlags)0; allFlagsThatMustMatch |= (isStatic ? BindingFlags.Static : BindingFlags.Instance); if (isStatic && inBaseClass) { allFlagsThatMustMatch |= BindingFlags.FlattenHierarchy; } allFlagsThatMustMatch |= ((visibility == MethodAttributes.Public) ? BindingFlags.Public : BindingFlags.NonPublic); if (inBaseClass) { queriedMembers.Add(policies.GetInheritedMemberInfo(member, reflectedType), allFlagsThatMustMatch); } else { queriedMembers.Add(member, allFlagsThatMustMatch); } } if (declaredOnly) { break; } inBaseClass = true; type = typeInfo.BaseType; } return(queriedMembers); }