From 4893d02da9dd5c98d493982a7304654feae5905f Mon Sep 17 00:00:00 2001 From: jfrijters Date: Tue, 10 Apr 2012 06:23:16 +0000 Subject: [PATCH] Moved member lookup by name to a common implementation that fixes a number of bugs and adds IgnoreCase support. --- reflect/Enums.cs | 1 + reflect/MethodSignature.cs | 5 + reflect/Type.cs | 203 ++++++++++++++++++------------------- 3 files changed, 102 insertions(+), 107 deletions(-) diff --git a/reflect/Enums.cs b/reflect/Enums.cs index 4d5af2e4..79333401 100644 --- a/reflect/Enums.cs +++ b/reflect/Enums.cs @@ -39,6 +39,7 @@ namespace IKVM.Reflection public enum BindingFlags { Default = 0, + IgnoreCase = 1, DeclaredOnly = 2, Instance = 4, Static = 8, diff --git a/reflect/MethodSignature.cs b/reflect/MethodSignature.cs index 7d184d57..76c9cb50 100644 --- a/reflect/MethodSignature.cs +++ b/reflect/MethodSignature.cs @@ -312,6 +312,11 @@ namespace IKVM.Reflection return new MethodSignature(returnType, parameterTypes, modifiers, callingConvention, genericParamCount); } + internal bool MatchParameterTypes(MethodSignature other) + { + return Util.ArrayEquals(other.parameterTypes, parameterTypes); + } + internal bool MatchParameterTypes(Type[] types) { return Util.ArrayEquals(types, parameterTypes); diff --git a/reflect/Type.cs b/reflect/Type.cs index e4dd303b..d3c5094d 100644 --- a/reflect/Type.cs +++ b/reflect/Type.cs @@ -521,7 +521,16 @@ namespace IKVM.Reflection public MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) { - MemberFilter filter = delegate(MemberInfo member, object filterCriteria) { return member.Name.Equals(filterCriteria); }; + MemberFilter filter; + if ((bindingAttr & BindingFlags.IgnoreCase) != 0) + { + name = name.ToLowerInvariant(); + filter = delegate(MemberInfo member, object filterCriteria) { return member.Name.ToLowerInvariant().Equals(filterCriteria); }; + } + else + { + filter = delegate(MemberInfo member, object filterCriteria) { return member.Name.Equals(filterCriteria); }; + } return FindMembers(type, bindingAttr, filter, name); } @@ -623,6 +632,76 @@ namespace IKVM.Reflection return list.ToArray(); } + private T GetMemberByName(string name, BindingFlags flags, Predicate filter) + where T : MemberInfo + { + CheckBaked(); + if ((flags & BindingFlags.IgnoreCase) != 0) + { + name = name.ToLowerInvariant(); + } + T found = null; + foreach (MemberInfo member in GetMembers()) + { + if (member is T && member.BindingFlagsMatch(flags)) + { + string memberName = member.Name; + if ((flags & BindingFlags.IgnoreCase) != 0) + { + memberName = memberName.ToLowerInvariant(); + } + if (memberName == name && (filter == null || filter((T)member))) + { + if (found != null) + { + throw new AmbiguousMatchException(); + } + found = (T)member; + } + } + } + if ((flags & BindingFlags.DeclaredOnly) == 0) + { + for (Type type = this.BaseType; (found == null || typeof(T) == typeof(MethodInfo)) && type != null; type = type.BaseType) + { + type.CheckBaked(); + foreach (MemberInfo member in type.GetMembers()) + { + if (member is T && member.BindingFlagsMatchInherited(flags)) + { + string memberName = member.Name; + if ((flags & BindingFlags.IgnoreCase) != 0) + { + memberName = memberName.ToLowerInvariant(); + } + if (memberName == name && (filter == null || filter((T)member))) + { + if (found != null) + { + MethodInfo mi; + // TODO does this depend on HideBySig vs HideByName? + if ((mi = found as MethodInfo) != null + && mi.MethodSignature.MatchParameterTypes(((MethodBase)member).MethodSignature)) + { + continue; + } + throw new AmbiguousMatchException(); + } + found = (T)member; + } + } + } + } + } + return found; + } + + private T GetMemberByName(string name, BindingFlags flags) + where T : MemberInfo + { + return GetMemberByName(name, flags, null); + } + public EventInfo GetEvent(string name) { return GetEvent(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); @@ -630,14 +709,7 @@ namespace IKVM.Reflection public EventInfo GetEvent(string name, BindingFlags bindingAttr) { - foreach (EventInfo evt in GetEvents(bindingAttr)) - { - if (evt.Name == name) - { - return evt; - } - } - return null; + return GetMemberByName(name, bindingAttr); } public EventInfo[] GetEvents() @@ -657,14 +729,7 @@ namespace IKVM.Reflection public FieldInfo GetField(string name, BindingFlags bindingAttr) { - foreach (FieldInfo field in GetFields(bindingAttr)) - { - if (field.Name == name) - { - return field; - } - } - return null; + return GetMemberByName(name, bindingAttr); } public FieldInfo[] GetFields() @@ -775,19 +840,7 @@ namespace IKVM.Reflection public MethodInfo GetMethod(string name, BindingFlags bindingAttr) { - MethodInfo found = null; - foreach (MethodInfo method in GetMethods(bindingAttr)) - { - if (method.Name == name) - { - if (found != null) - { - throw new AmbiguousMatchException(); - } - found = method; - } - } - return found; + return GetMemberByName(name, bindingAttr); } public MethodInfo GetMethod(string name, Type[] types) @@ -802,19 +855,8 @@ namespace IKVM.Reflection public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) { - MethodInfo found = null; - foreach (MethodInfo method in GetMethods(bindingAttr)) - { - if (method.Name == name && method.MethodSignature.MatchParameterTypes(types)) - { - if (found != null) - { - throw new AmbiguousMatchException(); - } - found = method; - } - } - return found; + return GetMemberByName(name, bindingAttr, + delegate(MethodInfo method) { return method.MethodSignature.MatchParameterTypes(types); }); } public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) @@ -840,14 +882,8 @@ namespace IKVM.Reflection public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) { - foreach (ConstructorInfo constructor in GetConstructors(bindingAttr)) - { - if (constructor.MethodSignature.MatchParameterTypes(types)) - { - return constructor; - } - } - return null; + return GetMemberByName(ConstructorInfo.ConstructorName, bindingAttr | BindingFlags.DeclaredOnly, + delegate(ConstructorInfo ctor) { return ctor.MethodSignature.MatchParameterTypes(types); }); } public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callingConvention, Type[] types, ParameterModifier[] modifiers) @@ -893,15 +929,8 @@ namespace IKVM.Reflection public Type GetNestedType(string name, BindingFlags bindingAttr) { - foreach (Type type in GetNestedTypes(bindingAttr)) - { - // FXBUG the namespace is ignored - if (type.__Name == name) - { - return type; - } - } - return null; + // FXBUG the namespace is ignored, so we can use GetMemberByName + return GetMemberByName(name, bindingAttr | BindingFlags.DeclaredOnly); } public Type[] GetNestedTypes() @@ -932,48 +961,17 @@ namespace IKVM.Reflection public PropertyInfo GetProperty(string name, BindingFlags bindingAttr) { - foreach (PropertyInfo prop in GetProperties(bindingAttr)) - { - if (prop.Name == name) - { - return prop; - } - } - return null; + return GetMemberByName(name, bindingAttr); } public PropertyInfo GetProperty(string name, Type returnType) { - PropertyInfo found = null; - foreach (PropertyInfo prop in GetProperties()) - { - if (prop.Name == name && prop.PropertyType.Equals(returnType)) - { - if (found != null) - { - throw new AmbiguousMatchException(); - } - found = prop; - } - } - return found; + return GetMemberByName(name, BindingFlags.Default, delegate(PropertyInfo prop) { return prop.PropertyType.Equals(returnType); }); } public PropertyInfo GetProperty(string name, Type[] types) { - PropertyInfo found = null; - foreach (PropertyInfo prop in GetProperties()) - { - if (prop.Name == name && MatchParameterTypes(prop.GetIndexParameters(), types)) - { - if (found != null) - { - throw new AmbiguousMatchException(); - } - found = prop; - } - } - return found; + return GetMemberByName(name, BindingFlags.Default, delegate(PropertyInfo prop) { return MatchParameterTypes(prop.GetIndexParameters(), types); }); } private static bool MatchParameterTypes(ParameterInfo[] parameters, Type[] types) @@ -1004,19 +1002,10 @@ namespace IKVM.Reflection public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { - PropertyInfo found = null; - foreach (PropertyInfo prop in GetProperties(bindingAttr)) - { - if (prop.Name == name && prop.PropertyType.Equals(returnType) && MatchParameterTypes(prop.GetIndexParameters(), types)) - { - if (found != null) - { - throw new AmbiguousMatchException(); - } - found = prop; - } - } - return found; + return GetMemberByName(name, bindingAttr, + delegate(PropertyInfo prop) { + return prop.PropertyType.Equals(returnType) && MatchParameterTypes(prop.GetIndexParameters(), types); + }); } public Type GetInterface(string name)