New tests.
[mono.git] / mcs / class / corlib / System / Type.cs
index 7e37c635f9cf09efce382fa575a86237fe9e1a14..a6d6f0d52f16dee34450ef32c1939198ccc7d6b1 100644 (file)
@@ -42,11 +42,9 @@ namespace System {
 
        [Serializable]
        [ClassInterface (ClassInterfaceType.None)]
-#if NET_2_0
        [ComVisible (true)]
        [ComDefaultInterface (typeof (_Type))]
-#endif
-       public abstract class Type : MemberInfo, IReflect, _Type, _MemberInfo {
+       public abstract class Type : MemberInfo, IReflect, _Type {
                
                internal RuntimeTypeHandle _impl;
 
@@ -55,7 +53,7 @@ namespace System {
                public static readonly MemberFilter FilterAttribute = new MemberFilter (FilterAttribute_impl);
                public static readonly MemberFilter FilterName = new MemberFilter (FilterName_impl);
                public static readonly MemberFilter FilterNameIgnoreCase = new MemberFilter (FilterNameIgnoreCase_impl);
-               public static readonly object Missing;
+               public static readonly object Missing = System.Reflection.Missing.Value;
 
                internal const BindingFlags DefaultBindingFlags =
                BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
@@ -64,11 +62,11 @@ namespace System {
                static bool FilterName_impl (MemberInfo m, object filterCriteria)
                {
                        string name = (string) filterCriteria;
-               if (name == null || name.Length == 0 )
+                       if (name == null || name.Length == 0 )
                                return false; // because m.Name cannot be null or empty
                                
                        if (name [name.Length-1] == '*')
-                               return string.Compare (name, 0, m.Name, 0, name.Length-1, false, CultureInfo.InvariantCulture) == 0;
+                               return string.CompareOrdinal (name, 0, m.Name, 0, name.Length-1) == 0;
 
                return name.Equals (m.Name);                    
                }
@@ -76,13 +74,13 @@ namespace System {
                static bool FilterNameIgnoreCase_impl (MemberInfo m, object filterCriteria)
                {
                        string name = (string) filterCriteria;
-               if (name == null || name.Length == 0 )
+                       if (name == null || name.Length == 0 )
                                return false; // because m.Name cannot be null or empty
                                
                        if (name [name.Length-1] == '*')
-                               return string.Compare (name, 0, m.Name, 0, name.Length-1, true, CultureInfo.InvariantCulture) == 0;
+                               return string.Compare (name, 0, m.Name, 0, name.Length-1, StringComparison.OrdinalIgnoreCase) == 0;
 
-                       return String.Compare (name, m.Name, true, CultureInfo.InvariantCulture) == 0;                          
+                       return string.Equals (name, m.Name, StringComparison.OrdinalIgnoreCase);
                }
 
                static bool FilterAttribute_impl (MemberInfo m, object filterCriteria)
@@ -211,7 +209,7 @@ namespace System {
                                if (IsInterface)
                                        return false;
 
-                               return !IsSubclassOf (typeof (ValueType));
+                               return !IsValueType;
                        }
                }
 
@@ -227,7 +225,11 @@ namespace System {
                        }
                }
 
-               public bool IsEnum {
+               public
+#if NET_4_0
+               virtual
+#endif
+               bool IsEnum {
                        get {
                                return IsSubclassOf (typeof (Enum));
                        }
@@ -329,7 +331,11 @@ namespace System {
                        }
                }
 
-               public bool IsSerializable {
+               public
+#if NET_4_0
+               virtual
+#endif
+               bool IsSerializable {
                        get {
                                if ((Attributes & TypeAttributes.Serializable) != 0)
                                        return true;
@@ -378,9 +384,7 @@ namespace System {
                        get {return MemberTypes.TypeInfo;}
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                override
-#endif
                public abstract Module Module {get;}
        
                public abstract string Namespace {get;}
@@ -391,17 +395,11 @@ namespace System {
                        }
                }
 
-#if NET_2_0
                public virtual RuntimeTypeHandle TypeHandle {
-                       get { return default (RuntimeTypeHandle); }
+                       get { throw new ArgumentException ("Derived class must provide implementation."); }
                }
-#else
-               public abstract RuntimeTypeHandle TypeHandle {get;}
-#endif
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public ConstructorInfo TypeInitializer {
                        get {
                                return GetConstructorImpl (
@@ -413,25 +411,219 @@ namespace System {
                        }
                }
 
+               /*
+                * This has NOTHING to do with getting the base type of an enum. Use
+                * Enum.GetUnderlyingType () for that.
+                */
                public abstract Type UnderlyingSystemType {get;}
 
                public override bool Equals (object o)
                {
+#if NET_4_0
+                       return Equals (o as Type);
+#else
+                       if (o == this)
+                               return true;
+
+                       Type me = UnderlyingSystemType;
+                       if (me == null)
+                               return false;
+                       return me.EqualsInternal (o as Type);
+#endif
+               }
+
+#if NET_4_0
+               public virtual bool Equals (Type o)
+               {
+                       if ((object)o == this)
+                               return true;
+                       if ((object)o == null)
+                               return false;
+                       Type me = UnderlyingSystemType;
+                       if ((object)me == null)
+                               return false;
+
+                       o = o.UnderlyingSystemType;
+                       if ((object)o == null)
+                               return false;
+                       if ((object)o == this)
+                               return true;
+                       return me.EqualsInternal (o);
+               }               
+#else
+               public bool Equals (Type o)
+               {
+
+                       if (o == this)
+                               return true;
                        if (o == null)
                                return false;
-                       
-                       Type cmp = o as Type;
-                       if (cmp == null)
+                       Type me = UnderlyingSystemType;
+                       if (me == null)
                                return false;
-                       return Equals (cmp);
+                       return me.EqualsInternal (o.UnderlyingSystemType);
+               }
+#endif
+#if NET_4_0
+               [MonoTODO ("Implement it properly once 4.0 impl details are known.")]
+               public static bool operator == (Type left, Type right)
+               {
+                       return Object.ReferenceEquals (left, right);
                }
 
-               public bool Equals (Type type) {
-                       if (type == null)
-                               return false;
-                       return UnderlyingSystemType.EqualsInternal (type.UnderlyingSystemType);
+               [MonoTODO ("Implement it properly once 4.0 impl details are known.")]
+               public static bool operator != (Type left, Type right)
+               {
+                       return !Object.ReferenceEquals (left, right);
+               }
+
+               [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+               public virtual Type GetEnumUnderlyingType () {
+                       if (!IsEnum)
+                               throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+                       var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+
+                       if (fields == null || fields.Length != 1)
+                               throw new ArgumentException ("An enum must have exactly one instance field", "enumType");
+
+                       return fields [0].FieldType;
+               }
+
+               [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+               public virtual string[] GetEnumNames () {
+                       if (!IsEnum)
+                               throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+                       var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+
+                       string [] result = new string [fields.Length];
+                       for (int i = 0; i < fields.Length; ++i)
+                               result [i] = fields [i].Name;
+
+                       return result;
+               }
+
+               NotImplementedException CreateNIE () {
+                       return new NotImplementedException ();
+               }
+
+               public virtual Array GetEnumValues () {
+                       if (!IsEnum)
+                               throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+                       throw CreateNIE ();
+               }
+
+               bool IsValidEnumType (Type type) {
+                       return (type.IsPrimitive && type != typeof (bool) && type != typeof (double) && type != typeof (float)) || type.IsEnum;
                }
 
+               [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+               public virtual string GetEnumName (object value) {
+                       if (value == null)
+                               throw new ArgumentException ("Value is null", "value");
+                       if (!IsValidEnumType (value.GetType ()))
+                               throw new ArgumentException ("Value is not the enum or a valid enum underlying type", "value");
+                       if (!IsEnum)
+                               throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+                       object obj = null;
+                       var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+                       
+                       for (int i = 0; i < fields.Length; ++i) {
+                               var fv = fields [i].GetValue (null);
+                               if (obj == null) {
+                                       try {
+                                               //XXX we can't use 'this' as argument as it might be an UserType
+                                               obj = Enum.ToObject (fv.GetType (), value);
+                                       } catch (OverflowException) {
+                                               return null;
+                                       } catch (InvalidCastException) {
+                                               throw new ArgumentException ("Value is not valid", "value");
+                                       }
+                               }
+                               if (fv.Equals (obj))
+                                       return fields [i].Name;
+                       }
+
+                       return null;
+               }
+
+               [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
+               public virtual bool IsEnumDefined (object value) {
+                       if (value == null)
+                               throw new ArgumentException ("Value is null", "value");
+                       if (!IsEnum)
+                               throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+                       Type vt = value.GetType ();
+                       if (!IsValidEnumType (vt) && vt != typeof (string))
+                               throw new InvalidOperationException ("Value is not the enum or a valid enum underlying type");
+
+                       var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+
+                       if (value is string) {
+                               for (int i = 0; i < fields.Length; ++i) {
+                                       if (fields [i].Name.Equals (value))
+                                               return true;
+                               }
+                       } else {
+                               if (vt != this && vt != GetEnumUnderlyingType ())
+                                       throw new ArgumentException ("Value is not the enum or a valid enum underlying type", "value");
+
+                               object obj = null;
+                               for (int i = 0; i < fields.Length; ++i) {
+                                       var fv = fields [i].GetValue (null);
+                                       if (obj == null) {
+                                               try {
+                                                       //XXX we can't use 'this' as argument as it might be an UserType
+                                                       obj = Enum.ToObject (fv.GetType (), value);
+                                               } catch (OverflowException) {
+                                                       return false;
+                                               } catch (InvalidCastException) {
+                                                       throw new ArgumentException ("Value is not valid", "value");
+                                               }
+                                       }
+                                       if (fv.Equals (obj))
+                                               return true;
+                               }
+                       }
+                       return false;
+               }
+       
+               public static Type GetType (string typeName, Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver)
+               {
+                       return GetType (typeName, assemblyResolver, typeResolver, false, false);
+               }
+       
+               public static Type GetType (string typeName, Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver, bool throwOnError)
+               {
+                       return GetType (typeName, assemblyResolver, typeResolver, throwOnError, false);
+               }
+       
+               public static Type GetType (string typeName, Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver, bool throwOnError, bool ignoreCase)
+               {
+                       TypeSpec spec = TypeSpec.Parse (typeName);
+                       return spec.Resolve (assemblyResolver, typeResolver, throwOnError, ignoreCase);
+               }
+
+               public virtual bool IsSecurityTransparent
+               {
+                       get { throw CreateNIE (); }
+               }
+
+               public virtual bool IsSecurityCritical
+               {
+                       get { throw CreateNIE (); }
+               }
+
+               public virtual bool IsSecuritySafeCritical
+               {
+                       get { throw CreateNIE (); }
+               }
+#endif
+               
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal extern bool EqualsInternal (Type type);
                
@@ -444,7 +636,7 @@ namespace System {
                public static Type GetType(string typeName)
                {
                        if (typeName == null)
-                               throw new ArgumentNullException ("typeName");
+                               throw new ArgumentNullException ("TypeName");
 
                        return internal_from_name (typeName, false, false);
                }
@@ -452,7 +644,7 @@ namespace System {
                public static Type GetType(string typeName, bool throwOnError)
                {
                        if (typeName == null)
-                               throw new ArgumentNullException ("typeName");
+                               throw new ArgumentNullException ("TypeName");
 
                        Type type = internal_from_name (typeName, throwOnError, false);
                        if (throwOnError && type == null)
@@ -464,7 +656,7 @@ namespace System {
                public static Type GetType(string typeName, bool throwOnError, bool ignoreCase)
                {
                        if (typeName == null)
-                               throw new ArgumentNullException ("typeName");
+                               throw new ArgumentNullException ("TypeName");
 
                        Type t = internal_from_name (typeName, throwOnError, ignoreCase);
                        if (throwOnError && t == null)
@@ -487,45 +679,60 @@ namespace System {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal extern static TypeCode GetTypeCodeInternal (Type type);
 
-               public static TypeCode GetTypeCode (Type type) {
-                       if (type == null)
-                               /* MS.NET returns this */
-                               return TypeCode.Empty;
+#if NET_4_0
+               protected virtual
+#endif
+               TypeCode GetTypeCodeImpl () {
+                       Type type = this;
+                       if (type is MonoType)
+                               return GetTypeCodeInternal (type);
 
                        type = type.UnderlyingSystemType;
 
                        if (!type.IsSystemType)
-                               return Type.GetTypeCode (typeof (object));
+                               return TypeCode.Object;
                        else
                                return GetTypeCodeInternal (type);
                }
 
-               [MonoTODO("Mono does not support COM")]
+               public static TypeCode GetTypeCode (Type type) {
+                       if (type == null)
+                               /* MS.NET returns this */
+                               return TypeCode.Empty;
+                       return type.GetTypeCodeImpl ();
+               }
+
+               [MonoTODO("This operation is currently not supported by Mono")]
                public static Type GetTypeFromCLSID (Guid clsid)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO("Mono does not support COM")]
+               [MonoTODO("This operation is currently not supported by Mono")]
                public static Type GetTypeFromCLSID (Guid clsid, bool throwOnError)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO("Mono does not support COM")]
+               [MonoTODO("This operation is currently not supported by Mono")]
                public static Type GetTypeFromCLSID (Guid clsid, string server)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO("Mono does not support COM")]
+               [MonoTODO("This operation is currently not supported by Mono")]
                public static Type GetTypeFromCLSID (Guid clsid, string server, bool throwOnError)
                {
                        throw new NotImplementedException ();
                }
 
                public static Type GetTypeFromHandle (RuntimeTypeHandle handle)
-               { 
+               {
+                       if (handle.Value == IntPtr.Zero)
+                               // This is not consistent with the other GetXXXFromHandle methods, but
+                               // MS.NET seems to do this
+                               return null;
+
                        return internal_from_handle (handle.Value);
                }
 
@@ -555,6 +762,9 @@ namespace System {
 
                public static RuntimeTypeHandle GetTypeHandle (object o)
                {
+                       if (o == null)
+                               throw new ArgumentNullException ();
+
                        return o.GetType().TypeHandle;
                }
 
@@ -569,9 +779,7 @@ namespace System {
                        return base.GetType ();
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public virtual bool IsSubclassOf (Type c)
                {
                        if (c == null || c == this)
@@ -612,15 +820,19 @@ namespace System {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);
 
-#if NET_2_0
                [ComVisible (true)]
-#endif         
                public virtual InterfaceMapping GetInterfaceMap (Type interfaceType) {
+                       if (!IsSystemType)
+                               throw new NotSupportedException ("Derived classes must provide an implementation.");
+                       if (!interfaceType.IsSystemType)
+                               throw new ArgumentException ("interfaceType", "Type is an user type");
                        InterfaceMapping res;
                        if (interfaceType == null)
                                throw new ArgumentNullException ("interfaceType");
                        if (!interfaceType.IsInterface)
                                throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "interfaceType");
+                       if (IsInterface)
+                               throw new ArgumentException ("'this' type cannot be an interface itself");
                        res.TargetType = this;
                        res.InterfaceType = interfaceType;
                        GetInterfaceMapData (this, interfaceType, out res.TargetMethods, out res.InterfaceMethods);
@@ -648,7 +860,12 @@ namespace System {
                                Type systemType = UnderlyingSystemType;
                                if (!systemType.IsSystemType)
                                        return false;
-                               return systemType.IsAssignableFrom (c);
+
+                               Type other = c.UnderlyingSystemType;
+                               if (!other.IsSystemType)
+                                       return false;
+
+                               return systemType.IsAssignableFrom (other);
                        }
 
                        if (!c.IsSystemType) {
@@ -662,7 +879,15 @@ namespace System {
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern virtual bool IsInstanceOfType (object o);
+               extern static bool IsInstanceOfType (Type type, object o);
+
+               public virtual bool IsInstanceOfType (object o)
+               {
+                       Type type = UnderlyingSystemType;
+                       if (!type.IsSystemType)
+                               return false;
+                       return IsInstanceOfType (type, o);
+               }
 
                public virtual int GetArrayRank ()
                {
@@ -701,12 +926,15 @@ namespace System {
                
                public override int GetHashCode()
                {
+                       Type t = UnderlyingSystemType;
+                       if (t != null && t != this)
+                               return t.GetHashCode ();
                        return (int)_impl.Value;
                }
 
                public MemberInfo[] GetMember (string name)
                {
-                       return GetMember (name, DefaultBindingFlags);
+                       return GetMember (name, MemberTypes.All, DefaultBindingFlags);
                }
                
                public virtual MemberInfo[] GetMember (string name, BindingFlags bindingAttr)
@@ -716,6 +944,8 @@ namespace System {
 
                public virtual MemberInfo[] GetMember (string name, MemberTypes type, BindingFlags bindingAttr)
                {
+                       if (name == null)
+                               throw new ArgumentNullException ("name");
                        if ((bindingAttr & BindingFlags.IgnoreCase) != 0)
                                return FindMembers (type, bindingAttr, FilterNameIgnoreCase, name);
                        else
@@ -757,7 +987,6 @@ namespace System {
                public MethodInfo GetMethod (string name, BindingFlags bindingAttr, Binder binder,
                                             Type[] types, ParameterModifier[] modifiers)
                {
-                       
                        return GetMethod (name, bindingAttr, binder, CallingConventions.Any, types, modifiers);
                }
 
@@ -930,26 +1159,20 @@ namespace System {
                        return typeof (MarshalByRefObject).IsAssignableFrom (this);
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public ConstructorInfo GetConstructor (Type[] types)
                {
-                       return GetConstructor (DefaultBindingFlags, null, CallingConventions.Any, types, null);
+                       return GetConstructor (BindingFlags.Public|BindingFlags.Instance, null, CallingConventions.Any, types, null);
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public ConstructorInfo GetConstructor (BindingFlags bindingAttr, Binder binder,
                                                       Type[] types, ParameterModifier[] modifiers)
                {
                        return GetConstructor (bindingAttr, binder, CallingConventions.Any, types, modifiers);
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public ConstructorInfo GetConstructor (BindingFlags bindingAttr, Binder binder,
                                                       CallingConventions callConvention,
                                                       Type[] types, ParameterModifier[] modifiers)
@@ -965,17 +1188,13 @@ namespace System {
                        return GetConstructorImpl (bindingAttr, binder, callConvention, types, modifiers);
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public ConstructorInfo[] GetConstructors ()
                {
                        return GetConstructors (BindingFlags.Public | BindingFlags.Instance);
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif         
                public abstract ConstructorInfo[] GetConstructors (BindingFlags bindingAttr);
 
                public virtual MemberInfo[] GetDefaultMembers ()
@@ -996,9 +1215,8 @@ namespace System {
 
                        // Console.WriteLine ("FindMembers for {0} (Type: {1}): {2}",
                        // this.FullName, this.GetType().FullName, this.obj_address());
-
-                       if ((memberType & MemberTypes.Constructor) != 0) {
-                               ConstructorInfo[] c = GetConstructors (bindingAttr);
+                       if ((memberType & MemberTypes.Method) != 0) {
+                               MethodInfo[] c = GetMethods (bindingAttr);
                                if (filter != null) {
                                        foreach (MemberInfo m in c) {
                                                if (filter (m, filterCriteria))
@@ -1008,8 +1226,8 @@ namespace System {
                                        l.AddRange (c);
                                }
                        }
-                       if ((memberType & MemberTypes.Event) != 0) {
-                               EventInfo[] c = GetEvents (bindingAttr);
+                       if ((memberType & MemberTypes.Constructor) != 0) {
+                               ConstructorInfo[] c = GetConstructors (bindingAttr);
                                if (filter != null) {
                                        foreach (MemberInfo m in c) {
                                                if (filter (m, filterCriteria))
@@ -1019,8 +1237,10 @@ namespace System {
                                        l.AddRange (c);
                                }
                        }
-                       if ((memberType & MemberTypes.Field) != 0) {
-                               FieldInfo[] c = GetFields (bindingAttr);
+                       if ((memberType & MemberTypes.Property) != 0) {
+                               PropertyInfo[] c = GetProperties (bindingAttr);
+
+
                                if (filter != null) {
                                        foreach (MemberInfo m in c) {
                                                if (filter (m, filterCriteria))
@@ -1029,9 +1249,10 @@ namespace System {
                                } else {
                                        l.AddRange (c);
                                }
+
                        }
-                       if ((memberType & MemberTypes.Method) != 0) {
-                               MethodInfo[] c = GetMethods (bindingAttr);
+                       if ((memberType & MemberTypes.Event) != 0) {
+                               EventInfo[] c = GetEvents (bindingAttr);
                                if (filter != null) {
                                        foreach (MemberInfo m in c) {
                                                if (filter (m, filterCriteria))
@@ -1041,22 +1262,14 @@ namespace System {
                                        l.AddRange (c);
                                }
                        }
-                       if ((memberType & MemberTypes.Property) != 0) {
-                               PropertyInfo[] c;
-                               int count = l.Count;
-                               Type ptype;
+                       if ((memberType & MemberTypes.Field) != 0) {
+                               FieldInfo[] c = GetFields (bindingAttr);
                                if (filter != null) {
-                                       ptype = this;
-                                       while ((l.Count == count) && (ptype != null)) {
-                                               c = ptype.GetProperties (bindingAttr);
-                                               foreach (MemberInfo m in c) {
-                                                       if (filter (m, filterCriteria))
-                                                               l.Add (m);
-                                               }
-                                               ptype = ptype.BaseType;
+                                       foreach (MemberInfo m in c) {
+                                               if (filter (m, filterCriteria))
+                                                       l.Add (m);
                                        }
                                } else {
-                                       c = GetProperties (bindingAttr);
                                        l.AddRange (c);
                                }
                        }
@@ -1072,7 +1285,31 @@ namespace System {
                                        l.AddRange (c);
                                }
                        }
-                       result = new MemberInfo [l.Count];
+
+                       switch (memberType) {
+                       case MemberTypes.Constructor :
+                               result = new ConstructorInfo [l.Count];
+                               break;
+                       case MemberTypes.Event :
+                               result = new EventInfo [l.Count];
+                               break;
+                       case MemberTypes.Field :
+                               result = new FieldInfo [l.Count];
+                               break;
+                       case MemberTypes.Method :
+                               result = new MethodInfo [l.Count];
+                               break;
+                       case MemberTypes.NestedType :
+                       case MemberTypes.TypeInfo :
+                               result = new Type [l.Count];
+                               break;
+                       case MemberTypes.Property :
+                               result = new PropertyInfo [l.Count];
+                               break;
+                       default :
+                               result = new MemberInfo [l.Count];
+                               break;
+                       }
                        l.CopyTo (result);
                        return result;
                }
@@ -1102,13 +1339,24 @@ namespace System {
                        return FullName;
                }
 
+               internal virtual bool IsCompilerContext {
+                       get {
+                               AssemblyBuilder builder = Assembly as AssemblyBuilder;
+                               return builder != null && builder.IsCompilerContext;
+                       }
+               }
+
+               internal virtual Type InternalResolve ()
+               {
+                       return UnderlyingSystemType;
+               }
+
                internal bool IsSystemType {
                        get {
                                return _impl.Value != IntPtr.Zero;
                        }
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                public virtual Type[] GetGenericArguments ()
                {
                        throw new NotSupportedException ();
@@ -1124,15 +1372,11 @@ namespace System {
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern Type GetGenericTypeDefinition_impl ();
+               internal extern Type GetGenericTypeDefinition_impl ();
 
                public virtual Type GetGenericTypeDefinition ()
                {
-                       Type res = GetGenericTypeDefinition_impl ();
-                       if (res == null)
-                               throw new InvalidOperationException ();
-
-                       return res;
+                       throw new NotSupportedException ("Derived classes must provide an implementation.");
                }
 
                public virtual extern bool IsGenericType {
@@ -1143,25 +1387,58 @@ namespace System {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                static extern Type MakeGenericType (Type gt, Type [] types);
 
-               public virtual Type MakeGenericType (params Type[] types)
+               static AssemblyBuilder PeelAssemblyBuilder (Type type)
                {
+                       if (type.Assembly is AssemblyBuilder)
+                               return (AssemblyBuilder)type.Assembly;
+
+                       if (type.HasElementType)
+                               return PeelAssemblyBuilder (type.GetElementType ());
+
+                       if (!type.IsGenericType || type.IsGenericParameter || type.IsGenericTypeDefinition)
+                               return null;
+
+                       foreach (Type arg in type.GetGenericArguments ()) {
+                               AssemblyBuilder ab = PeelAssemblyBuilder (arg);
+                               if (ab != null)
+                                       return ab;
+                       }
+                       return null;
+               }
+
+               public virtual Type MakeGenericType (params Type[] typeArguments)
+               {
+                       if (IsUserType)
+                               throw new NotSupportedException ();
                        if (!IsGenericTypeDefinition)
                                throw new InvalidOperationException ("not a generic type definition");
-                       if (types == null)
-                               throw new ArgumentNullException ("types");
+                       if (typeArguments == null)
+                               throw new ArgumentNullException ("typeArguments");
+                       if (GetGenericArguments().Length != typeArguments.Length)
+                               throw new ArgumentException (String.Format ("The type or method has {0} generic parameter(s) but {1} generic argument(s) where provided. A generic argument must be provided for each generic parameter.", GetGenericArguments ().Length, typeArguments.Length), "typeArguments");
+
+                       bool hasUserType = false;
+                       AssemblyBuilder compilerContext = null;
 
-                       Type[] systemTypes = new Type[types.Length];
-                       for (int i = 0; i < types.Length; ++i) {
-                               Type t = types [i];
+                       Type[] systemTypes = new Type[typeArguments.Length];
+                       for (int i = 0; i < typeArguments.Length; ++i) {
+                               Type t = typeArguments [i];
                                if (t == null)
-                                       throw new ArgumentNullException ("types");
+                                       throw new ArgumentNullException ("typeArguments");
 
-                               t = t.UnderlyingSystemType;
-                               if (t == null || !t.IsSystemType)
-                                       throw new ArgumentNullException ("types");
-                               systemTypes [i] = types [i].UnderlyingSystemType;
+                               if (!(t is MonoType))
+                                       hasUserType = true;
+                               if (t.IsCompilerContext)
+                                       compilerContext = PeelAssemblyBuilder (t);
+                               systemTypes [i] = t;
                        }
-                       
+
+                       if (hasUserType) {
+                               if (compilerContext != null)
+                                       return compilerContext.MakeGenericType (this, typeArguments);
+                               return new MonoGenericClass (this, typeArguments);
+                       }
+
                        Type res = MakeGenericType (this, systemTypes);
                        if (res == null)
                                throw new TypeLoadException ();
@@ -1206,6 +1483,9 @@ namespace System {
 
                public virtual GenericParameterAttributes GenericParameterAttributes {
                        get {
+                               if (!IsSystemType)
+                                       throw new NotSupportedException ("Derived classes must provide an implementation.");
+
                                if (!IsGenericParameter)
                                        throw new InvalidOperationException ();
 
@@ -1218,6 +1498,9 @@ namespace System {
 
                public virtual Type[] GetGenericParameterConstraints ()
                {
+                       if (!IsSystemType)
+                               throw new InvalidOperationException ();
+
                        if (!IsGenericParameter)
                                throw new InvalidOperationException ();
 
@@ -1235,12 +1518,16 @@ namespace System {
 
                public virtual Type MakeArrayType ()
                {
-                       return MakeArrayType (1);
+                       if (!IsSystemType)
+                               throw new NotSupportedException ("Derived classes must provide an implementation.");
+                       return make_array_type (0);
                }
 
                public virtual Type MakeArrayType (int rank)
                {
-                       if (rank < 1)
+                       if (!IsSystemType)
+                               throw new NotSupportedException ("Derived classes must provide an implementation.");
+                       if (rank < 1 || rank > 255)
                                throw new IndexOutOfRangeException ();
                        return make_array_type (rank);
                }
@@ -1250,11 +1537,22 @@ namespace System {
 
                public virtual Type MakeByRefType ()
                {
+                       if (!IsSystemType)
+                               throw new NotSupportedException ("Derived classes must provide an implementation.");
+                       if (IsByRef)
+                               throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
                        return make_byref_type ();
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern virtual Type MakePointerType ();
+               static extern Type MakePointerType (Type type);
+
+               public virtual Type MakePointerType ()
+               {
+                       if (!IsSystemType)
+                               throw new NotSupportedException ("Derived classes must provide an implementation.");
+                       return MakePointerType (this);
+               }
 
                public static Type ReflectionOnlyGetType (string typeName, 
                                                          bool throwIfNotFound, 
@@ -1269,7 +1567,7 @@ namespace System {
                        Assembly a;
                        try {
                                a = Assembly.ReflectionOnlyLoad (an);
-                       } catch (Exception ex) {
+                       } catch {
                                if (throwIfNotFound)
                                        throw;
                                return null;
@@ -1330,8 +1628,29 @@ namespace System {
                        return attrs;
                }                       
 
+
+#if NET_4_0 || BOOTSTRAP_NET_4_0
+               public virtual bool IsEquivalentTo (Type other)
+               {
+                       return this == other;
+               }
 #endif
 
+               /* 
+                * Return whenever this object is an instance of a user defined subclass
+                * of System.Type or an instance of TypeDelegator.
+                */
+               internal bool IsUserType {
+                       get {
+                               /* 
+                                * subclasses cannot modify _impl so if it is zero, it means the
+                                * type is not created by the runtime.
+                                */
+                               return _impl.Value == IntPtr.Zero &&
+                                       (GetType ().Assembly != typeof (Type).Assembly || GetType () == typeof (TypeDelegator));
+                       }
+               }
+
                void _Type.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
                {
                        throw new NotImplementedException ();