do not check order sequence if option /order was not used
[mono.git] / mcs / class / IKVM.Reflection / Type.cs
index 64ef33a7431e0b687729cae108c6432d71d5a6eb..bb0273c6ad0b5c9b2fbcbc6f75ab5d90a5b0b99d 100644 (file)
@@ -50,8 +50,10 @@ namespace IKVM.Reflection
                [Flags]
                protected enum TypeFlags
                {
-                       // for use by TypeBuilder
+                       // for use by TypeBuilder or TypeDefImpl
                        IsGenericTypeDefinition = 1,
+
+                       // for use by TypeBuilder
                        HasNestedTypes = 2,
                        Baked = 4,
 
@@ -59,9 +61,12 @@ namespace IKVM.Reflection
                        ValueType = 8,
                        NotValueType = 16,
 
-                       // for use by TypeDef, TypeBuilder or MissingType
+                       // for use by TypeDefImpl, TypeBuilder or MissingType
                        PotentialEnumOrValueType = 32,
                        EnumOrValueType = 64,
+
+                       // for use by TypeDefImpl
+                       NotGenericTypeDefinition = 128,
                }
 
                // prevent subclassing by outsiders
@@ -79,7 +84,7 @@ namespace IKVM.Reflection
 
                public static Binder DefaultBinder
                {
-                       get { return null; }
+                       get { return new DefaultBinder(); }
                }
 
                public sealed override MemberTypes MemberType
@@ -358,7 +363,8 @@ namespace IKVM.Reflection
                        get { return false; }
                }
 
-               internal virtual bool IsGenericTypeInstance
+               // .NET 4.5 API
+               public virtual bool IsConstructedGenericType
                {
                        get { return false; }
                }
@@ -521,7 +527,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);
                }
 
@@ -566,57 +581,151 @@ namespace IKVM.Reflection
                        return members.ToArray();
                }
 
-               public EventInfo GetEvent(string name)
+               private MemberInfo[] GetMembers<T>()
                {
-                       return GetEvent(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+                       if (typeof(T) == typeof(ConstructorInfo) || typeof(T) == typeof(MethodInfo))
+                       {
+                               return __GetDeclaredMethods();
+                       }
+                       else if (typeof(T) == typeof(FieldInfo))
+                       {
+                               return __GetDeclaredFields();
+                       }
+                       else if (typeof(T) == typeof(PropertyInfo))
+                       {
+                               return __GetDeclaredProperties();
+                       }
+                       else if (typeof(T) == typeof(EventInfo))
+                       {
+                               return __GetDeclaredEvents();
+                       }
+                       else if (typeof(T) == typeof(Type))
+                       {
+                               return __GetDeclaredTypes();
+                       }
+                       else
+                       {
+                               throw new InvalidOperationException();
+                       }
                }
 
-               public EventInfo GetEvent(string name, BindingFlags bindingAttr)
+               private T[] GetMembers<T>(BindingFlags flags)
+                       where T : MemberInfo
                {
-                       foreach (EventInfo evt in GetEvents(bindingAttr))
+                       CheckBaked();
+                       List<T> list = new List<T>();
+                       foreach (MemberInfo member in GetMembers<T>())
                        {
-                               if (evt.Name == name)
+                               if (member is T && member.BindingFlagsMatch(flags))
                                {
-                                       return evt;
+                                       list.Add((T)member);
                                }
                        }
-                       return null;
-               }
-
-               public EventInfo[] GetEvents()
-               {
-                       return GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+                       if ((flags & BindingFlags.DeclaredOnly) == 0)
+                       {
+                               for (Type type = this.BaseType; type != null; type = type.BaseType)
+                               {
+                                       type.CheckBaked();
+                                       foreach (MemberInfo member in type.GetMembers<T>())
+                                       {
+                                               if (member is T && member.BindingFlagsMatchInherited(flags))
+                                               {
+                                                       list.Add((T)member.SetReflectedType(this));
+                                               }
+                                       }
+                               }
+                       }
+                       return list.ToArray();
                }
 
-               public EventInfo[] GetEvents(BindingFlags bindingAttr)
+               private T GetMemberByName<T>(string name, BindingFlags flags, Predicate<T> filter)
+                       where T : MemberInfo
                {
-                       List<EventInfo> list = new List<EventInfo>();
-                       Type type = this;
-                       while (type != null)
+                       CheckBaked();
+                       if ((flags & BindingFlags.IgnoreCase) != 0)
                        {
-                               type.CheckBaked();
-                               foreach (EventInfo evt in type.__GetDeclaredEvents())
+                               name = name.ToLowerInvariant();
+                       }
+                       T found = null;
+                       foreach (MemberInfo member in GetMembers<T>())
+                       {
+                               if (member is T && member.BindingFlagsMatch(flags))
                                {
-                                       if (BindingFlagsMatch(evt.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
-                                               && BindingFlagsMatch(evt.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+                                       string memberName = member.Name;
+                                       if ((flags & BindingFlags.IgnoreCase) != 0)
                                        {
-                                               list.Add(evt);
+                                               memberName = memberName.ToLowerInvariant();
                                        }
-                               }
-                               if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
-                               {
-                                       if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
+                                       if (memberName == name && (filter == null || filter((T)member)))
                                        {
-                                               bindingAttr &= ~BindingFlags.Static;
+                                               if (found != null)
+                                               {
+                                                       throw new AmbiguousMatchException();
+                                               }
+                                               found = (T)member;
                                        }
-                                       type = type.BaseType;
                                }
-                               else
+                       }
+                       if ((flags & BindingFlags.DeclaredOnly) == 0)
+                       {
+                               for (Type type = this.BaseType; (found == null || typeof(T) == typeof(MethodInfo)) && type != null; type = type.BaseType)
                                {
-                                       break;
+                                       type.CheckBaked();
+                                       foreach (MemberInfo member in type.GetMembers<T>())
+                                       {
+                                               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.SetReflectedType(this);
+                                                       }
+                                               }
+                                       }
                                }
                        }
-                       return list.ToArray();
+                       return found;
+               }
+
+               private T GetMemberByName<T>(string name, BindingFlags flags)
+                       where T : MemberInfo
+               {
+                       return GetMemberByName<T>(name, flags, null);
+               }
+
+               public EventInfo GetEvent(string name)
+               {
+                       return GetEvent(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public EventInfo GetEvent(string name, BindingFlags bindingAttr)
+               {
+                       return GetMemberByName<EventInfo>(name, bindingAttr);
+               }
+
+               public EventInfo[] GetEvents()
+               {
+                       return GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+               }
+
+               public EventInfo[] GetEvents(BindingFlags bindingAttr)
+               {
+                       return GetMembers<EventInfo>(bindingAttr);
                }
 
                public FieldInfo GetField(string name)
@@ -626,14 +735,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<FieldInfo>(name, bindingAttr);
                }
 
                public FieldInfo[] GetFields()
@@ -643,32 +745,7 @@ namespace IKVM.Reflection
 
                public FieldInfo[] GetFields(BindingFlags bindingAttr)
                {
-                       List<FieldInfo> list = new List<FieldInfo>();
-                       CheckBaked();
-                       foreach (FieldInfo field in __GetDeclaredFields())
-                       {
-                               if (BindingFlagsMatch(field.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
-                                       && BindingFlagsMatch(field.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
-                               {
-                                       list.Add(field);
-                               }
-                       }
-                       if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
-                       {
-                               for (Type type = this.BaseType; type != null; type = type.BaseType)
-                               {
-                                       type.CheckBaked();
-                                       foreach (FieldInfo field in type.__GetDeclaredFields())
-                                       {
-                                               if ((field.Attributes & FieldAttributes.FieldAccessMask) > FieldAttributes.Private
-                                                       && BindingFlagsMatch(field.IsStatic, bindingAttr, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance))
-                                               {
-                                                       list.Add(field);
-                                               }
-                                       }
-                               }
-                       }
-                       return list.ToArray();
+                       return GetMembers<FieldInfo>(bindingAttr);
                }
 
                public Type[] GetInterfaces()
@@ -683,7 +760,6 @@ namespace IKVM.Reflection
 
                private static void AddInterfaces(List<Type> list, Type type)
                {
-                       type.CheckBaked();
                        foreach (Type iface in type.__GetDeclaredInterfaces())
                        {
                                if (!list.Contains(iface))
@@ -701,28 +777,42 @@ namespace IKVM.Reflection
                        foreach (MethodBase mb in __GetDeclaredMethods())
                        {
                                MethodInfo mi = mb as MethodInfo;
-                               if (mi != null
-                                       && BindingFlagsMatch(mi.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
-                                       && BindingFlagsMatch(mi.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
+                               if (mi != null && mi.BindingFlagsMatch(bindingAttr))
                                {
                                        list.Add(mi);
                                }
                        }
                        if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
                        {
+                               List<MethodInfo> baseMethods = new List<MethodInfo>();
+                               foreach (MethodInfo mi in list)
+                               {
+                                       if (mi.IsVirtual)
+                                       {
+                                               baseMethods.Add(mi.GetBaseDefinition());
+                                       }
+                               }
                                for (Type type = this.BaseType; type != null; type = type.BaseType)
                                {
                                        type.CheckBaked();
                                        foreach (MethodBase mb in type.__GetDeclaredMethods())
                                        {
                                                MethodInfo mi = mb as MethodInfo;
-                                               if (mi != null
-                                                       && (mi.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private
-                                                       && BindingFlagsMatch(mi.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
-                                                       && BindingFlagsMatch(mi.IsStatic, bindingAttr, BindingFlags.Static | BindingFlags.FlattenHierarchy, BindingFlags.Instance)
-                                                       && !FindMethod(list, mi))
+                                               if (mi != null && mi.BindingFlagsMatchInherited(bindingAttr))
                                                {
-                                                       list.Add(mi);
+                                                       if (mi.IsVirtual)
+                                                       {
+                                                               if (baseMethods == null)
+                                                               {
+                                                                       baseMethods = new List<MethodInfo>();
+                                                               }
+                                                               else if (baseMethods.Contains(mi.GetBaseDefinition()))
+                                                               {
+                                                                       continue;
+                                                               }
+                                                               baseMethods.Add(mi.GetBaseDefinition());
+                                                       }
+                                                       list.Add((MethodInfo)mi.SetReflectedType(this));
                                                }
                                        }
                                }
@@ -730,18 +820,6 @@ namespace IKVM.Reflection
                        return list.ToArray();
                }
 
-               private static bool FindMethod(List<MethodInfo> methods, MethodInfo method)
-               {
-                       foreach (MethodInfo m in methods)
-                       {
-                               if (m.Name == method.Name && m.MethodSignature.Equals(method.MethodSignature))
-                               {
-                                       return true;
-                               }
-                       }
-                       return false;
-               }
-
                public MethodInfo[] GetMethods()
                {
                        return GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
@@ -754,19 +832,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<MethodInfo>(name, bindingAttr);
                }
 
                public MethodInfo GetMethod(string name, Type[] types)
@@ -781,19 +847,21 @@ 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;
+                       // first we try an exact match and only if that fails we fall back to using the binder
+                       return GetMemberByName<MethodInfo>(name, bindingAttr,
+                               delegate(MethodInfo method) { return method.MethodSignature.MatchParameterTypes(types); })
+                               ?? GetMethodWithBinder<MethodInfo>(name, bindingAttr, binder ?? DefaultBinder, types, modifiers);
+               }
+
+               private T GetMethodWithBinder<T>(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+                       where T : MethodBase
+               {
+                       List<MethodBase> list = new List<MethodBase>();
+                       GetMemberByName<T>(name, bindingAttr, delegate(T method) {
+                               list.Add(method);
+                               return false;
+                       });
+                       return (T)binder.SelectMethod(bindingAttr, list.ToArray(), types, modifiers);
                }
 
                public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
@@ -809,19 +877,7 @@ namespace IKVM.Reflection
 
                public ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
                {
-                       CheckBaked();
-                       List<ConstructorInfo> list = new List<ConstructorInfo>();
-                       foreach (MethodBase mb in __GetDeclaredMethods())
-                       {
-                               ConstructorInfo constructor = mb as ConstructorInfo;
-                               if (constructor != null
-                                       && BindingFlagsMatch(constructor.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
-                                       && BindingFlagsMatch(constructor.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
-                               {
-                                       list.Add(constructor);
-                               }
-                       }
-                       return list.ToArray();
+                       return GetMembers<ConstructorInfo>(bindingAttr | BindingFlags.DeclaredOnly);
                }
 
                public ConstructorInfo GetConstructor(Type[] types)
@@ -831,14 +887,32 @@ namespace IKVM.Reflection
 
                public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
                {
-                       foreach (ConstructorInfo constructor in GetConstructors(bindingAttr))
+                       ConstructorInfo ci1 = null;
+                       if ((bindingAttr & BindingFlags.Instance) != 0)
                        {
-                               if (constructor.MethodSignature.MatchParameterTypes(types))
+                               ci1 = GetConstructorImpl(ConstructorInfo.ConstructorName, bindingAttr, binder, types, modifiers);
+                       }
+                       if ((bindingAttr & BindingFlags.Static) != 0)
+                       {
+                               ConstructorInfo ci2 = GetConstructorImpl(ConstructorInfo.TypeConstructorName, bindingAttr, binder, types, modifiers);
+                               if (ci2 != null)
                                {
-                                       return constructor;
+                                       if (ci1 != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       return ci2;
                                }
                        }
-                       return null;
+                       return ci1;
+               }
+
+               private ConstructorInfo GetConstructorImpl(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+               {
+                       // first we try an exact match and only if that fails we fall back to using the binder
+                       return GetMemberByName<ConstructorInfo>(name, bindingAttr | BindingFlags.DeclaredOnly,
+                               delegate(ConstructorInfo ctor) { return ctor.MethodSignature.MatchParameterTypes(types); })
+                               ?? GetMethodWithBinder<ConstructorInfo>(name, bindingAttr, binder ?? DefaultBinder, types, modifiers);
                }
 
                public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callingConvention, Type[] types, ParameterModifier[] modifiers)
@@ -865,17 +939,11 @@ namespace IKVM.Reflection
                        return null;
                }
 
-               public Type GetNestedType(string name)
-               {
-                       return GetNestedType(name, BindingFlags.Public);
-               }
-
-               public Type GetNestedType(string name, BindingFlags bindingAttr)
+               internal virtual Type FindNestedTypeIgnoreCase(TypeName lowerCaseName)
                {
-                       foreach (Type type in GetNestedTypes(bindingAttr))
+                       foreach (Type type in __GetDeclaredTypes())
                        {
-                               // FXBUG the namespace is ignored
-                               if (type.__Name == name)
+                               if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
                                {
                                        return type;
                                }
@@ -883,6 +951,17 @@ namespace IKVM.Reflection
                        return null;
                }
 
+               public Type GetNestedType(string name)
+               {
+                       return GetNestedType(name, BindingFlags.Public);
+               }
+
+               public Type GetNestedType(string name, BindingFlags bindingAttr)
+               {
+                       // FXBUG the namespace is ignored, so we can use GetMemberByName
+                       return GetMemberByName<Type>(name, bindingAttr | BindingFlags.DeclaredOnly);
+               }
+
                public Type[] GetNestedTypes()
                {
                        return GetNestedTypes(BindingFlags.Public);
@@ -890,16 +969,8 @@ namespace IKVM.Reflection
 
                public Type[] GetNestedTypes(BindingFlags bindingAttr)
                {
-                       CheckBaked();
-                       List<Type> list = new List<Type>();
-                       foreach (Type type in __GetDeclaredTypes())
-                       {
-                               if (BindingFlagsMatch(type.IsNestedPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic))
-                               {
-                                       list.Add(type);
-                               }
-                       }
-                       return list.ToArray();
+                       // FXBUG the namespace is ignored, so we can use GetMember
+                       return GetMembers<Type>(bindingAttr | BindingFlags.DeclaredOnly);
                }
 
                public PropertyInfo[] GetProperties()
@@ -909,33 +980,7 @@ namespace IKVM.Reflection
 
                public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
                {
-                       List<PropertyInfo> list = new List<PropertyInfo>();
-                       Type type = this;
-                       while (type != null)
-                       {
-                               type.CheckBaked();
-                               foreach (PropertyInfo property in type.__GetDeclaredProperties())
-                               {
-                                       if (BindingFlagsMatch(property.IsPublic, bindingAttr, BindingFlags.Public, BindingFlags.NonPublic)
-                                               && BindingFlagsMatch(property.IsStatic, bindingAttr, BindingFlags.Static, BindingFlags.Instance))
-                                       {
-                                               list.Add(property);
-                                       }
-                               }
-                               if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
-                               {
-                                       if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
-                                       {
-                                               bindingAttr &= ~BindingFlags.Static;
-                                       }
-                                       type = type.BaseType;
-                               }
-                               else
-                               {
-                                       break;
-                               }
-                       }
-                       return list.ToArray();
+                       return GetMembers<PropertyInfo>(bindingAttr);
                }
 
                public PropertyInfo GetProperty(string name)
@@ -945,64 +990,21 @@ 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<PropertyInfo>(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;
+                       const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
+                       return GetMemberByName<PropertyInfo>(name, flags, delegate(PropertyInfo prop) { return prop.PropertyType.Equals(returnType); })
+                               ?? GetPropertyWithBinder(name, flags, DefaultBinder, returnType, null, null);
                }
 
                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;
-               }
-
-               private static bool MatchParameterTypes(ParameterInfo[] parameters, Type[] types)
-               {
-                       if (parameters.Length == types.Length)
-                       {
-                               for (int i = 0; i < parameters.Length; i++)
-                               {
-                                       if (!parameters[i].ParameterType.Equals(types[i]))
-                                       {
-                                               return false;
-                                       }
-                               }
-                               return true;
-                       }
-                       return false;
+                       const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
+                       return GetMemberByName<PropertyInfo>(name, flags, delegate(PropertyInfo prop) { return prop.PropertySignature.MatchParameterTypes(types); })
+                               ?? GetPropertyWithBinder(name, flags, DefaultBinder, null, types, null);
                }
 
                public PropertyInfo GetProperty(string name, Type returnType, Type[] types)
@@ -1017,19 +1019,21 @@ 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<PropertyInfo>(name, bindingAttr,
+                               delegate(PropertyInfo prop) {
+                                       return prop.PropertyType.Equals(returnType) && prop.PropertySignature.MatchParameterTypes(types);
+                               })
+                               ?? GetPropertyWithBinder(name, bindingAttr, binder ?? DefaultBinder, returnType, types, modifiers);
+               }
+
+               private PropertyInfo GetPropertyWithBinder(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
+               {
+                       List<PropertyInfo> list = new List<PropertyInfo>();
+                       GetMemberByName<PropertyInfo>(name, bindingAttr, delegate(PropertyInfo property) {
+                               list.Add(property);
+                               return false;
+                       });
+                       return binder.SelectProperty(bindingAttr, list.ToArray(), returnType, types, modifiers);
                }
 
                public Type GetInterface(string name)
@@ -1041,16 +1045,26 @@ namespace IKVM.Reflection
                {
                        if (ignoreCase)
                        {
-                               throw new NotImplementedException();
+                               name = name.ToLowerInvariant();
                        }
+                       Type found = null;
                        foreach (Type type in GetInterfaces())
                        {
-                               if (type.FullName == name)
+                               string typeName = type.FullName;
+                               if (ignoreCase)
                                {
-                                       return type;
+                                       typeName = typeName.ToLowerInvariant();
+                               }
+                               if (typeName == name)
+                               {
+                                       if (found != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       found = type;
                                }
                        }
-                       return null;
+                       return found;
                }
 
                public Type[] FindInterfaces(TypeFilter filter, object filterCriteria)
@@ -1504,7 +1518,6 @@ namespace IKVM.Reflection
                        get { return Module.Assembly; }
                }
 
-               // note that interface/delegate co- and contravariance is not considered
                public bool IsAssignableFrom(Type type)
                {
                        if (this.Equals(type))
@@ -1529,13 +1542,24 @@ namespace IKVM.Reflection
                                Type e2 = type.GetElementType();
                                return e1.IsValueType == e2.IsValueType && e1.IsAssignableFrom(e2);
                        }
+                       else if (this.IsCovariant(type))
+                       {
+                               return true;
+                       }
                        else if (this.IsSealed)
                        {
                                return false;
                        }
                        else if (this.IsInterface)
                        {
-                               return Array.IndexOf(type.GetInterfaces(), this) != -1;
+                               foreach (Type iface in type.GetInterfaces())
+                               {
+                                       if (this.Equals(iface) || this.IsCovariant(iface))
+                                       {
+                                               return true;
+                                       }
+                               }
+                               return false;
                        }
                        else if (type.IsInterface)
                        {
@@ -1551,6 +1575,48 @@ namespace IKVM.Reflection
                        }
                }
 
+               private bool IsCovariant(Type other)
+               {
+                       if (this.IsConstructedGenericType
+                               && other.IsConstructedGenericType
+                               && this.GetGenericTypeDefinition() == other.GetGenericTypeDefinition())
+                       {
+                               Type[] typeParameters = GetGenericTypeDefinition().GetGenericArguments();
+                               for (int i = 0; i < typeParameters.Length; i++)
+                               {
+                                       Type t1 = this.GetGenericTypeArgument(i);
+                                       Type t2 = other.GetGenericTypeArgument(i);
+                                       if (t1.IsValueType != t2.IsValueType)
+                                       {
+                                               return false;
+                                       }
+                                       switch (typeParameters[i].GenericParameterAttributes & GenericParameterAttributes.VarianceMask)
+                                       {
+                                               case GenericParameterAttributes.Covariant:
+                                                       if (!t1.IsAssignableFrom(t2))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                               case GenericParameterAttributes.Contravariant:
+                                                       if (!t2.IsAssignableFrom(t1))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                               case GenericParameterAttributes.None:
+                                                       if (t1 != t2)
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                       }
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
                public bool IsSubclassOf(Type type)
                {
                        Type thisType = this.BaseType;
@@ -1712,7 +1778,7 @@ namespace IKVM.Reflection
                {
                        get
                        {
-                               IList<CustomAttributeData> cad = GetCustomAttributesData(this.Module.universe.System_AttributeUsageAttribute);
+                               IList<CustomAttributeData> cad = CustomAttributeData.__GetCustomAttributes(this, this.Module.universe.System_AttributeUsageAttribute, false);
                                if (cad.Count == 1)
                                {
                                        foreach (CustomAttributeNamedArgument arg in cad[0].NamedArguments)
@@ -1809,6 +1875,15 @@ namespace IKVM.Reflection
                        return __CreateMissingField(name, fieldType, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers));
                }
 
+               public PropertyInfo __CreateMissingProperty(string name, CallingConventions callingConvention, Type propertyType, CustomModifiers propertyTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers)
+               {
+                       PropertySignature sig = PropertySignature.Create(callingConvention,
+                               propertyType,
+                               parameterTypes,
+                               PackedCustomModifiers.CreateFromExternal(propertyTypeCustomModifiers, parameterTypeCustomModifiers, Util.NullSafeLength(parameterTypes)));
+                       return new MissingProperty(this, name, sig);
+               }
+
                internal virtual Type SetMetadataTokenForMissing(int token)
                {
                        return this;
@@ -1827,7 +1902,10 @@ namespace IKVM.Reflection
 
                private bool ResolvePotentialEnumOrValueType()
                {
-                       if (this.Assembly == this.Universe.Mscorlib || this.Assembly.GetName().Name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase))
+                       if (this.Assembly == this.Universe.Mscorlib
+                               || this.Assembly.GetName().Name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase)
+                               // check if mscorlib forwards the type (.NETCore profile reference mscorlib forwards System.Enum and System.ValueType to System.Runtime.dll)
+                               || this.Universe.Mscorlib.FindType(new TypeName(__Namespace, __Name)) == this)
                        {
                                typeFlags = (typeFlags & ~TypeFlags.PotentialEnumOrValueType) | TypeFlags.EnumOrValueType;
                                return true;
@@ -1848,18 +1926,45 @@ namespace IKVM.Reflection
                        }
                }
 
-               internal virtual IList<CustomAttributeData> GetInterfaceImplCustomAttributes(Type interfaceType, Type attributeType)
+               internal virtual Universe Universe
                {
-                       throw new NotSupportedException();
+                       get { return Module.universe; }
                }
 
-               internal virtual Universe Universe
+               internal sealed override bool BindingFlagsMatch(BindingFlags flags)
                {
-                       get { return Module.universe; }
+                       return BindingFlagsMatch(IsNestedPublic, flags, BindingFlags.Public, BindingFlags.NonPublic);
+               }
+
+               internal sealed override MemberInfo SetReflectedType(Type type)
+               {
+                       throw new InvalidOperationException();
+               }
+
+               internal override int GetCurrentToken()
+               {
+                       return this.MetadataToken;
+               }
+
+               internal sealed override List<CustomAttributeData> GetPseudoCustomAttributes(Type attributeType)
+               {
+                       // types don't have pseudo custom attributes
+                       return null;
+               }
+
+               // in .NET this is an extension method, but we target .NET 2.0, so we have an instance method
+               public TypeInfo GetTypeInfo()
+               {
+                       TypeInfo type = this as TypeInfo;
+                       if (type == null)
+                       {
+                               throw new MissingMemberException(this);
+                       }
+                       return type;
                }
        }
 
-       abstract class ElementHolderType : Type
+       abstract class ElementHolderType : TypeInfo
        {
                protected readonly Type elementType;
                private int token;
@@ -1970,14 +2075,20 @@ namespace IKVM.Reflection
                        elementType.CheckBaked();
                }
 
-               internal sealed override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               internal sealed override Universe Universe
                {
-                       return CustomAttributeData.EmptyList;
+                       get { return elementType.Universe; }
                }
 
-               internal sealed override Universe Universe
+               internal sealed override bool IsBaked
                {
-                       get { return elementType.Universe; }
+                       get { return elementType.IsBaked; }
+               }
+
+               internal sealed override int GetCurrentToken()
+               {
+                       // we don't have a token, so we return 0 (which is never a valid token)
+                       return 0;
                }
 
                internal abstract string GetSuffix();
@@ -2274,6 +2385,12 @@ namespace IKVM.Reflection
                                return new CustomModifiers();
                        }
 
+                       public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal)
+                       {
+                               fieldMarshal = new FieldMarshal();
+                               return false;
+                       }
+
                        public override MemberInfo Member
                        {
                                get { return method.IsConstructor ? (MethodBase)new ConstructorInfoImpl(method) : method; }
@@ -2281,7 +2398,7 @@ namespace IKVM.Reflection
 
                        public override int MetadataToken
                        {
-                               get { return 0x8000000; }
+                               get { return 0x08000000; }
                        }
 
                        internal override Module Module
@@ -2387,7 +2504,7 @@ namespace IKVM.Reflection
                }
        }
 
-       sealed class GenericTypeInstance : Type
+       sealed class GenericTypeInstance : TypeInfo
        {
                private readonly Type type;
                private readonly Type[] args;
@@ -2650,7 +2767,7 @@ namespace IKVM.Reflection
                        get { return true; }
                }
 
-               internal override bool IsGenericTypeInstance
+               public override bool IsConstructedGenericType
                {
                        get { return true; }
                }
@@ -2739,13 +2856,18 @@ namespace IKVM.Reflection
                        return this;
                }
 
-               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               internal override int GetCurrentToken()
+               {
+                       return type.GetCurrentToken();
+               }
+
+               internal override bool IsBaked
                {
-                       return type.GetCustomAttributesData(attributeType);
+                       get { return type.IsBaked; }
                }
        }
 
-       sealed class FunctionPointerType : Type
+       sealed class FunctionPointerType : TypeInfo
        {
                private readonly Universe universe;
                private readonly __StandAloneMethodSig sig;
@@ -2818,5 +2940,61 @@ namespace IKVM.Reflection
                {
                        return "<FunctionPtr>";
                }
+
+               internal override bool IsBaked
+               {
+                       get { return true; }
+               }
+       }
+
+       sealed class MarkerType : Type
+       {
+               // used by ILGenerator
+               internal static readonly Type Fault = new MarkerType();
+               internal static readonly Type Finally = new MarkerType();
+               internal static readonly Type Filter = new MarkerType();
+               // used by CustomModifiers and SignatureHelper
+               internal static readonly Type ModOpt = new MarkerType();
+               internal static readonly Type ModReq = new MarkerType();
+               // used by SignatureHelper
+               internal static readonly Type Sentinel = new MarkerType();
+               internal static readonly Type Pinned = new MarkerType();
+
+               private MarkerType() { }
+
+               public override Type BaseType
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override string Name
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override string FullName
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override Module Module
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               internal override bool IsBaked
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override bool __IsMissing
+               {
+                       get { throw new InvalidOperationException(); }
+               }
        }
 }