Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / corlib / System / Type.cs
index 9e5fd9f905590e0268e73ce11c9b41dd620de425..327c15b889c1931bbc867328b65c7407ef185284 100644 (file)
@@ -1,8 +1,9 @@
 //
 // System.Type.cs
 //
-// Author:
+// Authors:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Marek Safar (marek.safar@gmail.com)
 //
 // (C) Ximian, Inc.  http://www.ximian.com
 //
@@ -34,6 +35,7 @@ using System.Diagnostics;
 using System.Reflection;
 using System.Reflection.Emit;
 using System.Collections;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
 using System.Globalization;
@@ -42,10 +44,9 @@ namespace System {
 
        [Serializable]
        [ClassInterface (ClassInterfaceType.None)]
-#if NET_2_0
        [ComVisible (true)]
        [ComDefaultInterface (typeof (_Type))]
-#endif
+       [StructLayout (LayoutKind.Sequential)]
        public abstract class Type : MemberInfo, IReflect, _Type {
                
                internal RuntimeTypeHandle _impl;
@@ -55,7 +56,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;
@@ -68,7 +69,7 @@ namespace System {
                                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);                    
                }
@@ -80,9 +81,9 @@ namespace System {
                                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)
@@ -220,6 +221,14 @@ namespace System {
                                return IsCOMObjectImpl ();
                        }
                }
+               
+#if NET_4_5
+               public virtual bool IsConstructedGenericType {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+               }
+#endif
 
                public bool IsContextful {
                        get {
@@ -227,7 +236,11 @@ namespace System {
                        }
                }
 
-               public bool IsEnum {
+               public
+#if NET_4_0
+               virtual
+#endif
+               bool IsEnum {
                        get {
                                return IsSubclassOf (typeof (Enum));
                        }
@@ -329,7 +342,11 @@ namespace System {
                        }
                }
 
-               public bool IsSerializable {
+               public
+#if NET_4_0
+               virtual
+#endif
+               bool IsSerializable {
                        get {
                                if ((Attributes & TypeAttributes.Serializable) != 0)
                                        return true;
@@ -375,13 +392,14 @@ namespace System {
                }
 
                public override MemberTypes MemberType {
-                       get {return MemberTypes.TypeInfo;}
+                       get {
+                               return MemberTypes.TypeInfo;
+                       }
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
-               override
-#endif
-               public abstract Module Module {get;}
+               public abstract override Module Module {
+                       get;
+               }
        
                public abstract string Namespace {get;}
 
@@ -391,17 +409,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 (
@@ -421,21 +433,219 @@ namespace System {
 
                public override bool Equals (object o)
                {
-                       if (o == null)
-                               return false;
-                       
-                       Type cmp = o as Type;
-                       if (cmp == null)
+#if NET_4_0
+                       return Equals (o as Type);
+#else
+                       if (o == this)
+                               return true;
+
+                       Type me = UnderlyingSystemType;
+                       if (me == null)
                                return false;
-                       return Equals (cmp);
+                       return me.EqualsInternal (o as Type);
+#endif
                }
 
-               public bool Equals (Type o) {
+#if NET_4_0
+               public virtual bool Equals (Type o)
+               {
+                       if ((object)o == (object)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 == (object)this)
+                               return true;
+                       return me.EqualsInternal (o);
+               }               
+#else
+               public bool Equals (Type o)
+               {
+
+                       if (o == this)
+                               return true;
                        if (o == null)
                                return false;
-                       return UnderlyingSystemType.EqualsInternal (o.UnderlyingSystemType);
+                       Type me = UnderlyingSystemType;
+                       if (me == null)
+                               return false;
+                       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);
+               }
+
+               [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 [] names = new string [fields.Length];
+                       if (0 != names.Length) {
+                               for (int i = 0; i < fields.Length; ++i)
+                                       names [i] = fields [i].Name;
+                                       
+                               var et = GetEnumUnderlyingType ();
+                               var values = Array.CreateInstance (et, names.Length);
+                               for (int i = 0; i < fields.Length; ++i)
+                                       values.SetValue (fields [i].GetValue (null), i);
+                               MonoEnumInfo.SortEnums (et, values, names);
+                       }
+
+                       return names;
+               }
+
+               static 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);
                
@@ -448,11 +658,7 @@ namespace System {
                public static Type GetType(string typeName)
                {
                        if (typeName == null)
-#if NET_2_0
                                throw new ArgumentNullException ("TypeName");
-#else
-                               throw new ArgumentNullException ("className");
-#endif
 
                        return internal_from_name (typeName, false, false);
                }
@@ -460,11 +666,7 @@ namespace System {
                public static Type GetType(string typeName, bool throwOnError)
                {
                        if (typeName == null)
-#if NET_2_0
                                throw new ArgumentNullException ("TypeName");
-#else
-                               throw new ArgumentNullException ("className");
-#endif
 
                        Type type = internal_from_name (typeName, throwOnError, false);
                        if (throwOnError && type == null)
@@ -476,11 +678,7 @@ namespace System {
                public static Type GetType(string typeName, bool throwOnError, bool ignoreCase)
                {
                        if (typeName == null)
-#if NET_2_0
                                throw new ArgumentNullException ("TypeName");
-#else
-                               throw new ArgumentNullException ("className");
-#endif
 
                        Type t = internal_from_name (typeName, throwOnError, ignoreCase);
                        if (throwOnError && t == null)
@@ -503,12 +701,15 @@ namespace System {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal extern static TypeCode GetTypeCodeInternal (Type type);
 
-               public static TypeCode GetTypeCode (Type type) {
+#if NET_4_0
+               protected virtual
+#endif
+               TypeCode GetTypeCodeImpl () {
+                       Type type = this;
                        if (type is MonoType)
                                return GetTypeCodeInternal (type);
-                       if (type == null)
-                               /* MS.NET returns this */
-                               return TypeCode.Empty;
+                       if (type is TypeBuilder)
+                               return ((TypeBuilder)type).GetTypeCodeInternal ();
 
                        type = type.UnderlyingSystemType;
 
@@ -518,6 +719,13 @@ namespace System {
                                return GetTypeCodeInternal (type);
                }
 
+               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)
                {
@@ -545,13 +753,9 @@ namespace System {
                public static Type GetTypeFromHandle (RuntimeTypeHandle handle)
                {
                        if (handle.Value == IntPtr.Zero)
-#if NET_2_0
                                // This is not consistent with the other GetXXXFromHandle methods, but
                                // MS.NET seems to do this
                                return null;
-#else
-                               throw new ArgumentException ("The handle is invalid.");
-#endif
 
                        return internal_from_handle (handle.Value);
                }
@@ -583,11 +787,7 @@ namespace System {
                public static RuntimeTypeHandle GetTypeHandle (object o)
                {
                        if (o == null)
-#if NET_2_0
                                throw new ArgumentNullException ();
-#else
-                               throw new ArgumentNullException ("o");
-#endif
 
                        return o.GetType().TypeHandle;
                }
@@ -603,9 +803,7 @@ namespace System {
                        return base.GetType ();
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public virtual bool IsSubclassOf (Type c)
                {
                        if (c == null || c == this)
@@ -628,13 +826,13 @@ namespace System {
                        if (filter == null)
                                throw new ArgumentNullException ("filter");
 
-                       ArrayList ifaces = new ArrayList ();
+                       var ifaces = new List<Type> ();
                        foreach (Type iface in GetInterfaces ()) {
                                if (filter (iface, filterCriteria))
                                        ifaces.Add (iface);
                        }
 
-                       return (Type []) ifaces.ToArray (typeof (Type));
+                       return ifaces.ToArray ();
                }
                
                public Type GetInterface (string name) {
@@ -646,13 +844,15 @@ 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) {
-                       InterfaceMapping res;
+                       if (!IsSystemType)
+                               throw new NotSupportedException ("Derived classes must provide an implementation.");
                        if (interfaceType == null)
                                throw new ArgumentNullException ("interfaceType");
+                       if (!interfaceType.IsSystemType)
+                               throw new ArgumentException ("interfaceType", "Type is an user type");
+                       InterfaceMapping res;
                        if (!interfaceType.IsInterface)
                                throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "interfaceType");
                        if (IsInterface)
@@ -684,7 +884,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) {
@@ -698,7 +903,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 ()
                {
@@ -970,26 +1183,20 @@ namespace System {
                        return typeof (MarshalByRefObject).IsAssignableFrom (this);
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public ConstructorInfo GetConstructor (Type[] types)
                {
                        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)
@@ -1005,17 +1212,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 ()
@@ -1059,23 +1262,18 @@ namespace System {
                                }
                        }
                        if ((memberType & MemberTypes.Property) != 0) {
-                               PropertyInfo[] c;
-                               int count = l.Count;
-                               Type ptype;
+                               PropertyInfo[] c = GetProperties (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);
                                }
+
                        }
                        if ((memberType & MemberTypes.Event) != 0) {
                                EventInfo[] c = GetEvents (bindingAttr);
@@ -1165,13 +1363,25 @@ namespace System {
                        return FullName;
                }
 
+               internal virtual Type InternalResolve ()
+               {
+                       return UnderlyingSystemType;
+               }
+
                internal bool IsSystemType {
                        get {
                                return _impl.Value != IntPtr.Zero;
                        }
                }
+               
+#if NET_4_5
+               public virtual Type[] GenericTypeArguments {
+                       get {
+                               return IsGenericType ? GetGenericArguments () : EmptyTypes;
+                       }
+               }
+#endif
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                public virtual Type[] GetGenericArguments ()
                {
                        throw new NotSupportedException ();
@@ -1198,12 +1408,14 @@ namespace System {
                        [MethodImplAttribute(MethodImplOptions.InternalCall)]
                        get;
                }
-
+               
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                static extern Type MakeGenericType (Type gt, Type [] types);
 
                public virtual Type MakeGenericType (params Type[] typeArguments)
                {
+                       if (IsUserType)
+                               throw new NotSupportedException ();
                        if (!IsGenericTypeDefinition)
                                throw new InvalidOperationException ("not a generic type definition");
                        if (typeArguments == null)
@@ -1211,18 +1423,23 @@ namespace System {
                        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;
+
                        Type[] systemTypes = new Type[typeArguments.Length];
                        for (int i = 0; i < typeArguments.Length; ++i) {
                                Type t = typeArguments [i];
                                if (t == null)
                                        throw new ArgumentNullException ("typeArguments");
-                               if (!(t is EnumBuilder || t is TypeBuilder))
-                                       t = t.UnderlyingSystemType;
-                               if (t == null || !t.IsSystemType)
-                                       throw new ArgumentNullException ("typeArguments");
+
+                               if (!(t is MonoType))
+                                       hasUserType = true;
                                systemTypes [i] = t;
                        }
 
+                       if (hasUserType) {
+                               return new MonoGenericClass (this, typeArguments);
+                       }
+
                        Type res = MakeGenericType (this, systemTypes);
                        if (res == null)
                                throw new TypeLoadException ();
@@ -1267,6 +1484,9 @@ namespace System {
 
                public virtual GenericParameterAttributes GenericParameterAttributes {
                        get {
+                               if (!IsSystemType)
+                                       throw new NotSupportedException ("Derived classes must provide an implementation.");
+
                                if (!IsGenericParameter)
                                        throw new InvalidOperationException ();
 
@@ -1279,6 +1499,9 @@ namespace System {
 
                public virtual Type[] GetGenericParameterConstraints ()
                {
+                       if (!IsSystemType)
+                               throw new InvalidOperationException ();
+
                        if (!IsGenericParameter)
                                throw new InvalidOperationException ();
 
@@ -1296,14 +1519,17 @@ namespace System {
 
                public virtual Type MakeArrayType ()
                {
+                       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);
                }
 
@@ -1312,11 +1538,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, 
@@ -1344,29 +1581,43 @@ namespace System {
 
                public virtual StructLayoutAttribute StructLayoutAttribute {
                        get {
-                               LayoutKind kind;
-
-                               if (IsLayoutSequential)
-                                       kind = LayoutKind.Sequential;
-                               else if (IsExplicitLayout)
-                                       kind = LayoutKind.Explicit;
-                               else
-                                       kind = LayoutKind.Auto;
-
-                               StructLayoutAttribute attr = new StructLayoutAttribute (kind);
+#if NET_4_0
+                               throw new NotSupportedException ();
+#else
+                               return GetStructLayoutAttribute ();
+#endif
+                       }
+               }
+               
+               internal StructLayoutAttribute GetStructLayoutAttribute ()
+               {
+                       LayoutKind kind;
 
-                               if (IsUnicodeClass)
-                                       attr.CharSet = CharSet.Unicode;
-                               else if (IsAnsiClass)
-                                       attr.CharSet = CharSet.Ansi;
-                               else
-                                       attr.CharSet = CharSet.Auto;
+                       if (IsLayoutSequential)
+                               kind = LayoutKind.Sequential;
+                       else if (IsExplicitLayout)
+                               kind = LayoutKind.Explicit;
+                       else
+                               kind = LayoutKind.Auto;
 
-                               if (kind != LayoutKind.Auto)
-                                       GetPacking (out attr.Pack, out attr.Size);
+                       StructLayoutAttribute attr = new StructLayoutAttribute (kind);
 
-                               return attr;
+                       if (IsUnicodeClass)
+                               attr.CharSet = CharSet.Unicode;
+                       else if (IsAnsiClass)
+                               attr.CharSet = CharSet.Ansi;
+                       else
+                               attr.CharSet = CharSet.Auto;
+
+                       if (kind != LayoutKind.Auto) {
+                               int packing;
+                               GetPacking (out packing, out attr.Size);
+                               // 0 means no data provided, we end up with default value
+                               if (packing != 0)
+                                       attr.Pack = packing;
                        }
+
+                       return attr;
                }
 
                internal object[] GetPseudoCustomAttributes ()
@@ -1392,7 +1643,6 @@ namespace System {
                        return attrs;
                }                       
 
-#endif
 
 #if NET_4_0
                public virtual bool IsEquivalentTo (Type other)
@@ -1404,15 +1654,12 @@ namespace System {
                /* 
                 * Return whenever this object is an instance of a user defined subclass
                 * of System.Type or an instance of TypeDelegator.
+                * A user defined type is not simply the opposite of a system type.
+                * It's any class that's neither a SRE or runtime baked type.
                 */
-               internal bool IsUserType {
+               internal virtual 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));
+                               return true;
                        }
                }