2008-07-24 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / corlib / System / Type.cs
index 7e5b9ff89b8eef5179a69631065dc3339cc9a1cf..fcf8986ef0bb59da56d50cc99d7a2f4fc1ea6517 100644 (file)
@@ -64,7 +64,7 @@ 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] == '*')
@@ -76,7 +76,7 @@ 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] == '*')
@@ -208,15 +208,10 @@ namespace System {
 
                public bool IsClass {
                        get {
-                               //
-                               // This code used to probe for "this == typeof (System.Enum)", but in
-                               // The .NET Framework 1.0, the above test return false
-                               //
-                               if (this == typeof (System.ValueType))
-                                       return true;
                                if (IsInterface)
                                        return false;
-                               return !is_subtype_of (this, typeof (System.ValueType), false);
+
+                               return !IsSubclassOf (typeof (ValueType));
                        }
                }
 
@@ -234,12 +229,7 @@ namespace System {
 
                public bool IsEnum {
                        get {
-                               // This hack is needed because EnumBuilder's UnderlyingSystemType returns the enum's basetype
-                               if (this is EnumBuilder)
-                                       return true;
-
-                               return is_subtype_of (this, typeof (System.Enum), false) &&
-                                       this != typeof (System.Enum);
+                               return IsSubclassOf (typeof (Enum));
                        }
                }
 
@@ -341,9 +331,28 @@ namespace System {
 
                public bool IsSerializable {
                        get {
+                               if ((Attributes & TypeAttributes.Serializable) != 0)
+                                       return true;
+
                                // Enums and delegates are always serializable
-                               return (Attributes & TypeAttributes.Serializable) != 0 || IsEnum || 
-                                       is_subtype_of (this, typeof (System.Delegate), false);
+
+                               Type type = UnderlyingSystemType;
+                               if (type == null)
+                                       return false;
+
+                               // Fast check for system types
+                               if (type.IsSystemType)
+                                       return type_is_subtype_of (type, typeof (Enum), false) || type_is_subtype_of (type, typeof (Delegate), false);
+
+                               // User defined types depend on this behavior
+                               do {
+                                       if ((type == typeof (Enum)) || (type == typeof (Delegate)))
+                                               return true;
+
+                                       type = type.BaseType;
+                               } while (type != null);
+
+                               return false;
                        }
                }
 
@@ -382,7 +391,13 @@ namespace System {
                        }
                }
 
+#if NET_2_0
+               public virtual RuntimeTypeHandle TypeHandle {
+                       get { return default (RuntimeTypeHandle); }
+               }
+#else
                public abstract RuntimeTypeHandle TypeHandle {get;}
+#endif
 
 #if NET_2_0
                [ComVisible (true)]
@@ -398,6 +413,10 @@ 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)
@@ -405,15 +424,20 @@ namespace System {
                        if (o == null)
                                return false;
                        
-                       // TODO: return UnderlyingSystemType == o.UnderlyingSystemType;
                        Type cmp = o as Type;
                        if (cmp == null)
                                return false;
                        return Equals (cmp);
                }
 
+               public bool Equals (Type o) {
+                       if (o == null)
+                               return false;
+                       return UnderlyingSystemType.EqualsInternal (o.UnderlyingSystemType);
+               }
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern bool Equals (Type type);
+               internal extern bool EqualsInternal (Type type);
                
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private static extern Type internal_from_handle (IntPtr handle);
@@ -424,7 +448,11 @@ namespace System {
                public static Type GetType(string typeName)
                {
                        if (typeName == null)
-                               throw new ArgumentNullException ("typeName");
+#if NET_2_0
+                               throw new ArgumentNullException ("TypeName");
+#else
+                               throw new ArgumentNullException ("className");
+#endif
 
                        return internal_from_name (typeName, false, false);
                }
@@ -432,7 +460,11 @@ namespace System {
                public static Type GetType(string typeName, bool throwOnError)
                {
                        if (typeName == null)
-                               throw new ArgumentNullException ("typeName");
+#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)
@@ -444,7 +476,11 @@ namespace System {
                public static Type GetType(string typeName, bool throwOnError, bool ignoreCase)
                {
                        if (typeName == null)
-                               throw new ArgumentNullException ("typeName");
+#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)
@@ -468,6 +504,8 @@ namespace System {
                internal extern static TypeCode GetTypeCodeInternal (Type type);
 
                public static TypeCode GetTypeCode (Type type) {
+                       if (type is MonoType)
+                               return GetTypeCodeInternal (type);
                        if (type == null)
                                /* MS.NET returns this */
                                return TypeCode.Empty;
@@ -475,59 +513,68 @@ namespace System {
                        type = type.UnderlyingSystemType;
 
                        if (!type.IsSystemType)
-                               return Type.GetTypeCode (typeof (object));
+                               return TypeCode.Object;
                        else
                                return GetTypeCodeInternal (type);
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromCLSID (Guid clsid)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromCLSID (Guid clsid, bool throwOnError)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromCLSID (Guid clsid, string server)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromCLSID (Guid clsid, string server, bool throwOnError)
                {
                        throw new NotImplementedException ();
                }
 
                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);
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromProgID (string progID)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromProgID (string progID, bool throwOnError)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromProgID (string progID, string server)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO("Mono does not support COM")]
                public static Type GetTypeFromProgID (string progID, string server, bool throwOnError)
                {
                        throw new NotImplementedException ();
@@ -535,6 +582,13 @@ 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;
                }
 
@@ -544,17 +598,6 @@ namespace System {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal static extern bool type_is_assignable_from (Type a, Type b);
 
-               internal static bool is_subtype_of (Type a, Type b, bool check_interfaces)
-               {
-                       a = a.UnderlyingSystemType;
-                       b = b.UnderlyingSystemType;
-
-                       if (!a.IsSystemType || !b.IsSystemType)
-                               return false;
-                       else
-                               return type_is_subtype_of (a, b, check_interfaces);
-               }
-
                public new Type GetType ()
                {
                        return base.GetType ();
@@ -565,10 +608,19 @@ namespace System {
 #endif
                public virtual bool IsSubclassOf (Type c)
                {
-                       if (c == null)
+                       if (c == null || c == this)
                                return false;
 
-                       return (this != c) && is_subtype_of (this, c, false);
+                       // Fast check for system types
+                       if (IsSystemType)
+                               return c.IsSystemType && type_is_subtype_of (this, c, false);
+
+                       // User defined types depend on this behavior
+                       for (Type type = BaseType; type != null; type = type.BaseType)
+                               if (type == c)
+                                       return true;
+
+                       return false;
                }
 
                public virtual Type[] FindInterfaces (TypeFilter filter, object filterCriteria)
@@ -739,7 +791,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);
                }
 
@@ -860,6 +911,11 @@ namespace System {
                        if (types == null)
                                throw new ArgumentNullException ("types");
 
+                       foreach (Type t in types) {
+                               if (t == null)
+                                       throw new ArgumentNullException ("types");
+                       }
+
                        return GetPropertyImpl (name, bindingAttr, binder, returnType, types, modifiers);
                }
 
@@ -891,7 +947,7 @@ namespace System {
 
                protected virtual bool IsValueTypeImpl ()
                {
-                       if (this == typeof (Enum) || this == typeof (ValueType))
+                       if (this == typeof (ValueType) || this == typeof (Enum))
                                return false;
 
                        return IsSubclassOf (typeof (ValueType));
@@ -912,8 +968,7 @@ namespace System {
 #endif
                public ConstructorInfo GetConstructor (Type[] types)
                {
-                       return GetConstructorImpl (
-                               DefaultBindingFlags, null, CallingConventions.Any, types, null);
+                       return GetConstructor (BindingFlags.Public|BindingFlags.Instance, null, CallingConventions.Any, types, null);
                }
 
 #if NET_2_0
@@ -922,8 +977,7 @@ namespace System {
                public ConstructorInfo GetConstructor (BindingFlags bindingAttr, Binder binder,
                                                       Type[] types, ParameterModifier[] modifiers)
                {
-                       return GetConstructorImpl (
-                               bindingAttr, binder, CallingConventions.Any, types, modifiers);
+                       return GetConstructor (bindingAttr, binder, CallingConventions.Any, types, modifiers);
                }
 
 #if NET_2_0
@@ -936,6 +990,11 @@ namespace System {
                        if (types == null)
                                throw new ArgumentNullException ("types");
 
+                       foreach (Type t in types) {
+                               if (t == null)
+                                       throw new ArgumentNullException ("types");
+                       }
+
                        return GetConstructorImpl (bindingAttr, binder, callConvention, types, modifiers);
                }
 
@@ -1088,8 +1147,8 @@ namespace System {
                        throw new NotSupportedException ();
                }
 
-               public abstract bool ContainsGenericParameters {
-                       get;
+               public virtual bool ContainsGenericParameters {
+                       get { return false; }
                }
 
                public virtual extern bool IsGenericTypeDefinition {
@@ -1109,12 +1168,7 @@ namespace System {
                        return res;
                }
 
-               public extern bool IsGenericInstance {
-                       [MethodImplAttribute(MethodImplOptions.InternalCall)]
-                       get;
-               }
-
-               public extern bool IsGenericType {
+               public virtual extern bool IsGenericType {
                        [MethodImplAttribute(MethodImplOptions.InternalCall)]
                        get;
                }
@@ -1122,15 +1176,28 @@ namespace System {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                static extern Type MakeGenericType (Type gt, Type [] types);
 
-               public virtual Type MakeGenericType (params Type[] types)
+               public virtual Type MakeGenericType (params Type[] typeArguments)
                {
-                       if (types == null)
-                               throw new ArgumentNullException ("types");
-                       foreach (Type t in types) {
+                       if (!IsGenericTypeDefinition)
+                               throw new InvalidOperationException ("not a generic type definition");
+                       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");
+
+                       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 ("typeArguments");
+                               systemTypes [i] = typeArguments [i].UnderlyingSystemType;
                        }
-                       Type res = MakeGenericType (this, types);
+
+                       Type res = MakeGenericType (this, systemTypes);
                        if (res == null)
                                throw new TypeLoadException ();
                        return res;
@@ -1148,6 +1215,15 @@ namespace System {
                        }
                }
 
+               public bool IsVisible {
+                       get {
+                               if (IsNestedPublic)
+                                       return DeclaringType.IsVisible;
+
+                               return IsPublic;
+                       }
+               }
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern int GetGenericParameterPosition ();
                
@@ -1183,7 +1259,7 @@ namespace System {
                        return GetGenericParameterConstraints_impl ();
                }
 
-               public virtual MethodInfo DeclaringMethod {
+               public virtual MethodBase DeclaringMethod {
                        get {
                                return null;
                        }
@@ -1215,12 +1291,25 @@ namespace System {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern virtual Type MakePointerType ();
 
-               [MonoTODO]
                public static Type ReflectionOnlyGetType (string typeName, 
-                                                                                                 bool throwIfNotFound, 
-                                                                                                 bool ignoreCase)
+                                                         bool throwIfNotFound, 
+                                                         bool ignoreCase)
                {
-                       throw new NotImplementedException ();
+                       if (typeName == null)
+                               throw new ArgumentNullException ("typeName");
+                       int idx = typeName.IndexOf (',');
+                       if (idx < 0 || idx == 0 || idx == typeName.Length - 1)
+                               throw new ArgumentException ("Assembly qualifed type name is required", "typeName");
+                       string an = typeName.Substring (idx + 1);
+                       Assembly a;
+                       try {
+                               a = Assembly.ReflectionOnlyLoad (an);
+                       } catch {
+                               if (throwIfNotFound)
+                                       throw;
+                               return null;
+                       }
+                       return a.GetType (typeName.Substring (0, idx), throwIfNotFound, ignoreCase);
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -1260,6 +1349,8 @@ namespace System {
                        /* IsSerializable returns true for delegates/enums as well */
                        if ((Attributes & TypeAttributes.Serializable) != 0)
                                count ++;
+                       if ((Attributes & TypeAttributes.Import) != 0)
+                               count ++;
 
                        if (count == 0)
                                return null;
@@ -1268,6 +1359,8 @@ namespace System {
 
                        if ((Attributes & TypeAttributes.Serializable) != 0)
                                attrs [count ++] = new SerializableAttribute ();
+                       if ((Attributes & TypeAttributes.Import) != 0)
+                               attrs [count ++] = new ComImportAttribute ();
 
                        return attrs;
                }