* attribute.cs (GetMarshal): Work even if "DefineCustom" is
[mono.git] / mcs / class / corlib / System / MonoType.cs
index a76368810838f07ef1ec472f6c951dda5884bcec..7c145c730d73245c98768a31966493c674c1dbc5 100644 (file)
@@ -1,17 +1,40 @@
 //
 // System.MonoType
 //
-// Sean MacIsaac (macisaac@ximian.com)
-// Paolo Molaro (lupus@ximian.com)
-// Patrik Torstensson (patrik.torstensson@labs2.com)
+// Authors: 
+//     Sean MacIsaac (macisaac@ximian.com)
+//     Paolo Molaro (lupus@ximian.com)
+//     Patrik Torstensson (patrik.torstensson@labs2.com)
+//     Gonzalo Paniagua (gonzalo@ximian.com)
 //
-// (C) 2001 Ximian, Inc.
+// (c) 2001-2003 Ximian, Inc.
+// Copyright (C) 2003-2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System.Globalization;
 using System.Reflection;
 using System.Runtime.CompilerServices;
-using System.Globalization;
 using System.Runtime.Serialization;
+using System.Security;
 
 namespace System
 {
@@ -64,7 +87,7 @@ namespace System
                        if (types == null) {
                                if (count > 1)
                                        throw new AmbiguousMatchException ();
-                               return found;
+                               return (ConstructorInfo) CheckMethodSecurity (found);
                        }
                        match = new MethodBase [count];
                        if (count == 1)
@@ -79,11 +102,16 @@ namespace System
                        }
                        if (binder == null)
                                binder = Binder.DefaultBinder;
-                       return (ConstructorInfo)binder.SelectMethod (bindingAttr, match, types, modifiers);
+                       return (ConstructorInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr);
+               internal extern ConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
+
+               public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
+               {
+                       return GetConstructors_internal (bindingAttr, this);
+               }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern EventInfo InternalGetEvent (string name, BindingFlags bindingAttr);
@@ -97,14 +125,24 @@ namespace System
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern override EventInfo[] GetEvents (BindingFlags bindingAttr);
+               internal extern EventInfo[] GetEvents_internal (BindingFlags bindingAttr, Type reflected_type);
+
+               public override EventInfo[] GetEvents (BindingFlags bindingAttr)
+               {
+                       return GetEvents_internal (bindingAttr, this);
+               }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern override FieldInfo GetField (string name, BindingFlags bindingAttr);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern override FieldInfo[] GetFields (BindingFlags bindingAttr);
+               internal extern FieldInfo[] GetFields_internal (BindingFlags bindingAttr, Type reflected_type);
 
+               public override FieldInfo[] GetFields (BindingFlags bindingAttr)
+               {
+                       return GetFields_internal (bindingAttr, this);
+               }
+               
                public override Type GetInterface (string name, bool ignoreCase)
                {
                        if (name == null)
@@ -131,50 +169,79 @@ namespace System
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern override MethodInfo[] GetMethods (BindingFlags bindingAttr);
+               internal extern MethodInfo [] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
+
+               public override MethodInfo [] GetMethods (BindingFlags bindingAttr)
+               {
+                       return GetMethodsByName (null, bindingAttr, false, this);
+               }
 
                protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr,
                                                             Binder binder,
                                                             CallingConventions callConvention,
                                                             Type[] types, ParameterModifier[] modifiers)
                {
-                       MethodInfo[] methods = GetMethods (bindingAttr);
                        bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
+                       MethodInfo[] methods = GetMethodsByName (name, bindingAttr, ignoreCase, this);
                        MethodInfo found = null;
                        MethodBase[] match;
+                       int typesLen = (types != null) ? types.Length : 0;
                        int count = 0;
+                       
                        foreach (MethodInfo m in methods) {
-                               if (String.Compare (m.Name, name, ignoreCase, CultureInfo.InvariantCulture) != 0)
-                                       continue;
                                // Under MS.NET, Standard|HasThis matches Standard...
                                if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
                                        continue;
                                found = m;
                                count++;
                        }
+
                        if (count == 0)
                                return null;
-                       if (types == null) {
-                               if (count > 1)
-                                       throw new AmbiguousMatchException ();
-                               return found;
-                       }
+                       
+                       if (count == 1 && typesLen == 0) 
+                               return (MethodInfo) CheckMethodSecurity (found);
+
                        match = new MethodBase [count];
                        if (count == 1)
                                match [0] = found;
                        else {
                                count = 0;
                                foreach (MethodInfo m in methods) {
-                                       if (String.Compare (m.Name, name, ignoreCase, CultureInfo.InvariantCulture) != 0)
-                                               continue;
                                        if (callConvention != CallingConventions.Any && ((m.CallingConvention & callConvention) != callConvention))
                                                continue;
                                        match [count++] = m;
                                }
                        }
+                       
+                       if (types == null) 
+                               return (MethodInfo) CheckMethodSecurity (Binder.FindMostDerivedMatch (match));
+
                        if (binder == null)
                                binder = Binder.DefaultBinder;
-                       return (MethodInfo)binder.SelectMethod (bindingAttr, match, types, modifiers);
+                       
+                       return (MethodInfo) CheckMethodSecurity (binder.SelectMethod (bindingAttr, match, types, modifiers));
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern MethodInfo GetCorrespondingInflatedMethod (MethodInfo generic);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern ConstructorInfo GetCorrespondingInflatedConstructor (ConstructorInfo generic);
+
+               internal override MethodInfo GetMethod (MethodInfo fromNoninstanciated)
+                {
+                        return GetCorrespondingInflatedMethod (fromNoninstanciated);
+                }
+
+               internal override ConstructorInfo GetConstructor (ConstructorInfo fromNoninstanciated)
+               {
+                        return GetCorrespondingInflatedConstructor (fromNoninstanciated);
+               }
+
+               internal override FieldInfo GetField (FieldInfo fromNoninstanciated)
+               {
+                       return GetField (fromNoninstanciated.Name);
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -184,55 +251,31 @@ namespace System
                public extern override Type[] GetNestedTypes (BindingFlags bindingAttr);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern override PropertyInfo[] GetProperties( BindingFlags bindingAttr);
+               internal extern PropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);
+
+               public override PropertyInfo [] GetProperties (BindingFlags bindingAttr)
+               {
+                       return GetPropertiesByName (null, bindingAttr, false, this);
+               }
 
-               [MonoTODO]
                protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr,
                                                                 Binder binder, Type returnType,
                                                                 Type[] types,
                                                                 ParameterModifier[] modifiers)
                {
-                       // fixme: needs to use the binder, and send the modifiers to that binder
-                       if (null == name || types == null)
-                               throw new ArgumentNullException ();
-                       
-                       PropertyInfo ret = null;
-                       PropertyInfo [] props = GetProperties(bindingAttr);
                        bool ignoreCase = ((bindingAttr & BindingFlags.IgnoreCase) != 0);
+                       PropertyInfo [] props = GetPropertiesByName (name, bindingAttr, ignoreCase, this);
+                       int count = props.Length;
+                       if (count == 0)
+                               return null;
+                       
+                       if (count == 1 && (types == null || types.Length == 0)) 
+                               return props [0];
 
-                       foreach (PropertyInfo info in props) {
-                                       if (String.Compare (info.Name, name, ignoreCase, CultureInfo.InvariantCulture) != 0) 
-                                               continue;
-
-                                       if (returnType != null && info.PropertyType != returnType)
-                                                       continue;
-
-                                       if (types.Length > 0) {
-                                               ParameterInfo[] parameterInfo = info.GetIndexParameters ();
-
-                                               if (parameterInfo.Length != types.Length)
-                                                       continue;
-
-                                               int i;
-                                               bool match = true;
-
-                                               for (i = 0; i < types.Length; i ++)
-                                                       if (parameterInfo [i].ParameterType != types [i]) {
-                                                               match = false;
-                                                               break;
-                                                       }
-
-                                               if (!match)
-                                                       continue;
-                                       }
-
-                                       if (null != ret)
-                                               throw new AmbiguousMatchException();
-
-                                       ret = info;
-                       }
-
-                       return ret;
+                       if (binder == null)
+                               binder = Binder.DefaultBinder;
+                       
+                       return binder.SelectProperty (bindingAttr, props, returnType, types, modifiers);
                }
 
                protected override bool HasElementTypeImpl ()
@@ -288,7 +331,7 @@ namespace System
                        if ((invokeAttr & BindingFlags.SetField) != 0 && ((args == null) || args.Length != 1))
                                throw new ArgumentException ("invokeAttr");
                        if ((namedParameters != null) && ((args == null) || args.Length < namedParameters.Length))
-                               throw new ArgumentException ("namedParameters");
+                               throw new ArgumentException ("namedParameters cannot be more than named arguments in number");
 
                        /* set some defaults if none are provided :-( */
                        if ((invokeAttr & (BindingFlags.Public|BindingFlags.NonPublic)) == 0)
@@ -304,8 +347,12 @@ namespace System
                                ConstructorInfo[] ctors = GetConstructors (invokeAttr);
                                object state = null;
                                MethodBase ctor = binder.BindToMethod (invokeAttr, ctors, ref args, modifiers, culture, namedParameters, out state);
-                               if (ctor == null)
-                                       throw new MissingMethodException ();
+                               if (ctor == null) {
+                                       if (this.IsValueType && args == null)
+                                               return Activator.CreateInstanceInternal (this);
+                                       
+                                       throw new MissingMethodException ("Constructor on type '" + FullName + "' not found.");
+                               }
                                object result = ctor.Invoke (target, invokeAttr, binder, args, culture);
                                binder.ReorderArgumentArray (ref args, state);
                                return result;
@@ -315,33 +362,26 @@ namespace System
                                name = attr.MemberName;
                        }
                        bool ignoreCase = (invokeAttr & BindingFlags.IgnoreCase) != 0;
+                       bool throwMissingMethodException = false;
+                       bool throwMissingFieldException = false;
                        if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
-                               MethodInfo[] methods = GetMethods (invokeAttr);
+                               MethodInfo[] methods = GetMethodsByName (name, invokeAttr, ignoreCase, this);
                                object state = null;
-                               int i, count = 0;
-                               for (i = 0; i < methods.Length; ++i) {
-                                       if (String.Compare (methods [i].Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
-                                               count++;
+                               MethodBase m = binder.BindToMethod (invokeAttr, methods, ref args, modifiers, culture, namedParameters, out state);
+                               if (m == null) {
+                                       throwMissingMethodException = true;
+                               } else {
+                                       object result = m.Invoke (target, invokeAttr, binder, args, culture);
+                                       binder.ReorderArgumentArray (ref args, state);
+                                       return result;
                                }
-                               MethodBase[] smethods = new MethodBase [count];
-                               count = 0;
-                               for (i = 0; i < methods.Length; ++i) {
-                                       if (String.Compare (methods [i].Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0)
-                                               smethods [count++] = methods [i];
-                               }
-                               MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
-                               if (m == null)
-                                       throw new MissingMethodException ();
-                               object result = m.Invoke (target, invokeAttr, binder, args, culture);
-                               binder.ReorderArgumentArray (ref args, state);
-                               return result;
                        }
                        if ((invokeAttr & BindingFlags.GetField) != 0) {
                                FieldInfo f = GetField (name, invokeAttr);
                                if (f != null) {
                                        return f.GetValue (target);
                                } else if ((invokeAttr & BindingFlags.GetProperty) == 0) {
-                                       throw new MissingFieldException ();
+                                       throwMissingFieldException = true;
                                }
                                /* try GetProperty */
                        } else if ((invokeAttr & BindingFlags.SetField) != 0) {
@@ -350,62 +390,73 @@ namespace System
                                        f.SetValue (target, args [0]);
                                        return null;
                                } else if ((invokeAttr & BindingFlags.SetProperty) == 0) {
-                                       throw new MissingFieldException ();
+                                       throwMissingFieldException = true;
                                }
                                /* try SetProperty */
                        }
                        if ((invokeAttr & BindingFlags.GetProperty) != 0) {
-                               PropertyInfo[] properties = GetProperties (invokeAttr);
+                               PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
                                object state = null;
                                int i, count = 0;
                                for (i = 0; i < properties.Length; ++i) {
-                                       if (String.Compare (properties [i].Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0 && (properties [i].GetGetMethod () != null))
+                                       if ((properties [i].GetGetMethod (true) != null))
                                                count++;
                                }
                                MethodBase[] smethods = new MethodBase [count];
                                count = 0;
                                for (i = 0; i < properties.Length; ++i) {
-                                       MethodBase mb = properties [i].GetGetMethod ();
-                                       if (String.Compare (properties [i].Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0 && (mb != null))
+                                       MethodBase mb = properties [i].GetGetMethod (true);
+                                       if (mb != null)
                                                smethods [count++] = mb;
                                }
                                MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
-                               if (m == null)
-                                       throw new MissingFieldException ();
-                               object result = m.Invoke (target, invokeAttr, binder, args, culture);
-                               binder.ReorderArgumentArray (ref args, state);
-                               return result;
+                               if (m == null) {
+                                       throwMissingFieldException = true;
+                               } else {
+                                       object result = m.Invoke (target, invokeAttr, binder, args, culture);
+                                       binder.ReorderArgumentArray (ref args, state);
+                                       return result;
+                               }
                        } else if ((invokeAttr & BindingFlags.SetProperty) != 0) {
-                               PropertyInfo[] properties = GetProperties (invokeAttr);
+                               PropertyInfo[] properties = GetPropertiesByName (name, invokeAttr, ignoreCase, this);
                                object state = null;
                                int i, count = 0;
                                for (i = 0; i < properties.Length; ++i) {
-                                       if (String.Compare (properties [i].Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0 && (properties [i].GetSetMethod () != null))
+                                       if (properties [i].GetSetMethod (true) != null)
                                                count++;
                                }
                                MethodBase[] smethods = new MethodBase [count];
                                count = 0;
                                for (i = 0; i < properties.Length; ++i) {
-                                       MethodBase mb = properties [i].GetSetMethod ();
-                                       if (String.Compare (properties [i].Name, name, ignoreCase, CultureInfo.InvariantCulture) == 0 && (mb != null))
+                                       MethodBase mb = properties [i].GetSetMethod (true);
+                                       if (mb != null)
                                                smethods [count++] = mb;
                                }
                                MethodBase m = binder.BindToMethod (invokeAttr, smethods, ref args, modifiers, culture, namedParameters, out state);
-                               if (m == null)
-                                       throw new MissingFieldException ();
-                               object result = m.Invoke (target, invokeAttr, binder, args, culture);
-                               binder.ReorderArgumentArray (ref args, state);
-                               return result;
+                               if (m == null) {
+                                       throwMissingFieldException = true;
+                               } else {
+                                       object result = m.Invoke (target, invokeAttr, binder, args, culture);
+                                       binder.ReorderArgumentArray (ref args, state);
+                                       return result;
+                               }
                        }
+                       if (throwMissingMethodException)
+                               throw new MissingMethodException();
+                       if (throwMissingFieldException)
+                               throw new MissingFieldException();
+
                        return null;
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern override Type GetElementType ();
 
-               public extern override Type UnderlyingSystemType {
-                       [MethodImplAttribute(MethodImplOptions.InternalCall)]
-                       get;
+               public override Type UnderlyingSystemType {
+                       get {
+                               // This has _nothing_ to do with getting the base type of an enum etc.
+                               return this;
+                       }
                }
 
                public extern override Assembly Assembly {
@@ -415,12 +466,12 @@ namespace System
 
                public override string AssemblyQualifiedName {
                        get {
-                               return getFullName () + ", " + Assembly.ToString ();
+                               return getFullName (true, true);
                        }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern string getFullName();
+               private extern string getFullName(bool full_name, bool assembly_qualified);
 
                public extern override Type BaseType {
                        [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -429,7 +480,7 @@ namespace System
 
                public override string FullName {
                        get {
-                               return getFullName ();
+                               return getFullName (true, false);
                        }
                }
 
@@ -451,6 +502,11 @@ namespace System
 
                public override object[] GetCustomAttributes (Type attributeType, bool inherit)
                {
+                       if (attributeType == null)
+                       {
+                               throw new ArgumentNullException("attributeType");
+                       }
+                       
                        return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
                }
 
@@ -503,7 +559,15 @@ namespace System
                        UnitySerializationHolder.GetTypeData (this, info, context);
                }
 
-#if NET_1_2
+               public override string ToString()
+               {
+                       return getFullName (false, false);
+               }
+
+#if NET_2_0 || BOOTSTRAP_NET_2_0
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern override Type [] GetGenericArguments ();
+
                public extern override bool HasGenericArguments {
                        [MethodImplAttribute(MethodImplOptions.InternalCall)]
                        get;
@@ -537,5 +601,19 @@ namespace System
                        get;
                }
 #endif
+
+               private MethodBase CheckMethodSecurity (MethodBase mb)
+               {
+                       if (!SecurityManager.SecurityEnabled || (mb == null))
+                               return mb;
+
+                       // Sadly we have no way to know which kind of security action this is
+                       // so we must do it the hard way. Actually this isn't so bad 
+                       // because we can skip the (mb.Attributes & MethodAttributes.HasSecurity)
+                       // icall required (and do it ourselves)
+
+                       // this (unlike the Invoke step) is _and stays_ a LinkDemand (caller)
+                       return SecurityManager.ReflectedLinkDemandQuery (mb) ? mb : null;
+               }
        }
 }