New tests.
[mono.git] / mcs / class / corlib / System / MonoType.cs
index 99782f8b9c92affc2135c0944bfcbc58b6ca9d62..fe3bca9630b553fcffe19b47b5b6b7d64d126d1b 100644 (file)
@@ -30,6 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System.Collections.Generic;
 using System.Globalization;
 using System.Reflection;
 using System.Runtime.CompilerServices;
@@ -38,14 +39,21 @@ using System.Security;
 
 namespace System
 {
+       // Contains information about the type which is expensive to compute
+       internal class MonoTypeInfo {
+               public string full_name;
+               public ConstructorInfo default_ctor;
+       }
+               
        [Serializable]
        internal class MonoType : Type, ISerializable
        {
+               [NonSerialized]
+               MonoTypeInfo type_info;
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private static extern void type_from_obj (MonoType type, Object obj);
                
-               [MonoTODO]
                internal MonoType (Object obj)
                {
                        // this should not be used - lupus
@@ -56,7 +64,21 @@ namespace System
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private static extern TypeAttributes get_attributes (Type type);
+
+               internal ConstructorInfo GetDefaultConstructor () {
+                       ConstructorInfo ctor = null;
+                       
+                       if (type_info == null)
+                               type_info = new MonoTypeInfo ();
+                       if ((ctor = type_info.default_ctor) == null) {
+                               const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic;
        
+                               ctor = type_info.default_ctor = GetConstructor (flags,  null, CallingConventions.Any, Type.EmptyTypes, null);
+                       }
+
+                       return ctor;
+               }
+
                protected override TypeAttributes GetAttributeFlagsImpl ()
                {
                        return get_attributes (this);
@@ -67,11 +89,20 @@ namespace System
                                                                       CallingConventions callConvention,
                                                                       Type[] types,
                                                                       ParameterModifier[] modifiers)
+               {
+                       ConstructorInfo[] methods = GetConstructors (bindingAttr);
+                       return GetConstructorImpl (methods, bindingAttr, binder, callConvention, types, modifiers);
+               }
+
+               internal static ConstructorInfo GetConstructorImpl (ConstructorInfo[] methods, BindingFlags bindingAttr,
+                                                                      Binder binder,
+                                                                      CallingConventions callConvention,
+                                                                      Type[] types,
+                                                                      ParameterModifier[] modifiers)
                {
                        if (bindingAttr == BindingFlags.Default)
                                bindingAttr = BindingFlags.Public | BindingFlags.Instance;
 
-                       ConstructorInfo[] methods = GetConstructors (bindingAttr);
                        ConstructorInfo found = null;
                        MethodBase[] match;
                        int count = 0;
@@ -151,9 +182,12 @@ namespace System
                        Type[] interfaces = GetInterfaces();
 
                        foreach (Type type in interfaces) {
-                               if (String.Compare (type.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
+                               /*We must compare against the generic type definition*/
+                               Type t = type.IsGenericType ? type.GetGenericTypeDefinition () : type;
+
+                               if (String.Compare (t.Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
                                        return type;
-                               if (String.Compare (type.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
+                               if (String.Compare (t.FullName, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
                                        return type;
                        }
 
@@ -230,17 +264,24 @@ namespace System
 
                internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
                 {
+                       if (fromNoninstanciated == null)
+                               throw new ArgumentNullException ("fromNoninstanciated");
                         return GetCorrespondingInflatedMethod (fromNoninstanciated);
                 }
 
                internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
                {
+                       if (fromNoninstanciated == null)
+                               throw new ArgumentNullException ("fromNoninstanciated");
                         return GetCorrespondingInflatedConstructor (fromNoninstanciated);
                }
 
                internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
                {
-                       return GetField (fromNoninstanciated.Name);
+                       /* create sensible flags from given FieldInfo */
+                       BindingFlags flags = fromNoninstanciated.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
+                       flags |= fromNoninstanciated.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
+                       return GetField (fromNoninstanciated.Name, flags);
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -268,12 +309,13 @@ namespace System
                        if (count == 0)
                                return null;
                        
-                       if (count == 1 && (types == null || types.Length == 0)) 
+                       if (count == 1 && (types == null || types.Length == 0) && 
+                           (returnType == null || returnType == props[0].PropertyType))
                                return props [0];
 
                        if (binder == null)
                                binder = Binder.DefaultBinder;
-                       
+
                        return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
                }
 
@@ -299,34 +341,43 @@ namespace System
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                protected extern override bool IsPrimitiveImpl ();
 
-               protected override bool IsValueTypeImpl ()
+               public override bool IsSubclassOf (Type type)
                {
-                       return type_is_subtype_of (this, typeof (System.ValueType), false) &&
-                               this != typeof (System.ValueType) &&
-                               this != typeof (System.Enum);
+                       if (type == null)
+                               throw new ArgumentNullException ("type");
+
+                       return base.IsSubclassOf (type);
                }
-               
+
                public override object InvokeMember (string name, BindingFlags invokeAttr,
                                                     Binder binder, object target, object[] args,
                                                     ParameterModifier[] modifiers,
                                                     CultureInfo culture, string[] namedParameters)
                {
+                       const string bindingflags_arg = "bindingFlags";
+
 
                        if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
                                if ((invokeAttr & (BindingFlags.GetField |
                                                BindingFlags.GetField | BindingFlags.GetProperty |
                                                BindingFlags.SetProperty)) != 0)
-                                       throw new ArgumentException ("invokeAttr");
+                                       throw new ArgumentException (bindingflags_arg);
                        } else if (name == null)
                                throw new ArgumentNullException ("name");
                        if ((invokeAttr & BindingFlags.GetField) != 0 && (invokeAttr & BindingFlags.SetField) != 0)
-                               throw new ArgumentException ("invokeAttr");
+                               throw new ArgumentException ("Cannot specify both Get and Set on a field.", bindingflags_arg);
                        if ((invokeAttr & BindingFlags.GetProperty) != 0 && (invokeAttr & BindingFlags.SetProperty) != 0)
-                               throw new ArgumentException ("invokeAttr");
-                       if ((invokeAttr & BindingFlags.InvokeMethod) != 0 && (invokeAttr & (BindingFlags.SetProperty|BindingFlags.SetField)) != 0)
-                               throw new ArgumentException ("invokeAttr");
+                               throw new ArgumentException ("Cannot specify both Get and Set on a property.", bindingflags_arg);
+                       if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
+                               if ((invokeAttr & BindingFlags.SetField) != 0)
+                                       throw new ArgumentException ("Cannot specify Set on a field and Invoke on a method.", bindingflags_arg);
+                               if ((invokeAttr & BindingFlags.SetProperty) != 0)
+                                       throw new ArgumentException ("Cannot specify Set on a property and Invoke on a method.", bindingflags_arg);
+                       }
                        if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
                                throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
+                       if ((invokeAttr & (BindingFlags.InvokeMethod|BindingFlags.CreateInstance|BindingFlags.GetField|BindingFlags.SetField|BindingFlags.GetProperty|BindingFlags.SetProperty)) == 0)
+                               throw new ArgumentException ("Must specify binding flags describing the invoke operation required.", bindingflags_arg);
 
                        /* set some defaults if none are provided :-( */
                        if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
@@ -363,6 +414,8 @@ namespace System
                        if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
                                MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
                                object state = null;
+                               if (args == null)
+                                       args = new object [0];
                                MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
                                if (m == null) {
                                        if (methods.Length > 0)
@@ -370,6 +423,11 @@ namespace System
                                        else
                                                throwMissingMethodDescription = "Cannot find method " + name + ".";
                                } else {
+                                       ParameterInfo[] parameters = m.GetParameters();
+                                       for (int i = 0; i < parameters.Length; ++i) {
+                                               if (System.Reflection.Missing.Value == args [i] && (parameters [i].Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.HasDefault)
+                                                       throw new ArgumentException ("Used Missing.Value for argument without default value", "parameters");
+                                       }
                                        object result = m.Invoke (target, invokeAttr, binder, args, culture);
                                        binder.ReorderArgumentArray (ref args, state);
                                        return result;
@@ -384,11 +442,12 @@ namespace System
                                }
                                /* try GetProperty */
                        } else if ((invokeAttr & BindingFlags.SetField) != 0) {
-                               if ((args == null) || args.Length != 1)
-                                       throw new ArgumentException ("invokeAttr");
-
                                FieldInfo f = GetField (name, invokeAttr);
                                if (f != null) {
+                                       if (args == null)
+                                               throw new ArgumentNullException ("providedArgs");
+                                       if ((args == null) || args.Length != 1)
+                                               throw new ArgumentException ("Only the field value can be specified to set a field value.", bindingflags_arg);
                                        f.SetValue (target, args [0]);
                                        return null;
                                } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
@@ -482,7 +541,14 @@ namespace System
 
                public override string FullName {
                        get {
-                               return getFullName (true, false);
+                               string fullName;
+                               // This doesn't need locking
+                               if (type_info == null)
+                                       type_info = new MonoTypeInfo ();
+                               if ((fullName = type_info.full_name) == null)
+                                       fullName = type_info.full_name = getFullName (true, false);
+
+                               return fullName;
                        }
                }
 
@@ -517,7 +583,7 @@ namespace System
 
                public override MemberTypes MemberType {
                        get {
-                               if (DeclaringType != null)
+                               if (DeclaringType != null && !IsGenericParameter)
                                        return MemberTypes.NestedType;
                                else
                                        return MemberTypes.TypeInfo;
@@ -569,7 +635,6 @@ namespace System
                        return getFullName (false, false);
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern override Type [] GetGenericArguments ();
 
@@ -600,10 +665,34 @@ namespace System
                        [MethodImplAttribute(MethodImplOptions.InternalCall)]
                        get;
                }
+
+               public override Type GetGenericTypeDefinition () {
+                       Type res = GetGenericTypeDefinition_impl ();
+                       if (res == null)
+                               throw new InvalidOperationException ();
+
+                       return res;
+               }
+
+#if NET_4_0
+               public override IList<CustomAttributeData> GetCustomAttributesData () {
+                       return CustomAttributeData.GetCustomAttributes (this);
+               }
+
+
+               public override Array GetEnumValues () {
+                       if (!IsEnum)
+                               throw new ArgumentException ("Type is not an enumeration", "enumType");
+
+                       return Enum.GetValues (this);
+               }
 #endif
 
-               private MethodBase CheckMethodSecurity (MethodBase mb)
+               static MethodBase CheckMethodSecurity (MethodBase mb)
                {
+#if NET_2_1
+                       return mb;
+#else
                        if (!SecurityManager.SecurityEnabled || (mb == null))
                                return mb;
 
@@ -614,6 +703,29 @@ namespace System
 
                        // this (unlike the Invoke step) is _and stays_ a LinkDemand (caller)
                        return SecurityManager.ReflectedLinkDemandQuery (mb) ? mb : null;
+#endif
                }
+
+#if NET_4_0
+               //seclevel { transparent = 0, safe-critical = 1, critical = 2}
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern int get_core_clr_security_level ();
+
+               public override bool IsSecurityTransparent
+               {
+                       get { return get_core_clr_security_level () == 0; }
+               }
+
+               public override bool IsSecurityCritical
+               {
+                       get { return get_core_clr_security_level () > 0; }
+               }
+
+               public override bool IsSecuritySafeCritical
+               {
+                       get { return get_core_clr_security_level () == 1; }
+               }
+#endif
+
        }
 }