2008-06-02 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / corlib / System / MonoType.cs
index 893986e4000dd58880fd81920eded7596e5189e1..59b99e053190fcc05197cea67701accc03c68de4 100644 (file)
@@ -270,12 +270,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);
                }
 
@@ -314,22 +315,34 @@ namespace System
                                                     ParameterModifier[] modifiers,
                                                     CultureInfo culture, string[] namedParameters)
                {
+#if NET_2_0
+                       const string bindingflags_arg = "bindingFlags";
+#else
+                       const string bindingflags_arg = "invokeAttr";
+#endif
+
 
                        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)
@@ -373,6 +386,15 @@ 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");
+                                       }
+                                       bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1], 
+                                               typeof (ParamArrayAttribute)) : false;
+                                       if (hasParamArray)
+                                               ReorderParamArrayArguments (ref args, m);
                                        object result = m.Invoke (target, invokeAttr, binder, args, culture);
                                        binder.ReorderArgumentArray (ref args, state);
                                        return result;
@@ -387,11 +409,14 @@ 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 NET_2_0
+                                       if (args == null)
+                                               throw new ArgumentNullException ("providedArgs");
+#endif
+                                       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) {
@@ -418,6 +443,11 @@ namespace System
                                if (m == null) {
                                        throwMissingFieldException = true;
                                } else {
+                                       ParameterInfo[] parameters = m.GetParameters();
+                                       bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1], 
+                                               typeof (ParamArrayAttribute)) : false;
+                                       if (hasParamArray)
+                                               ReorderParamArrayArguments (ref args, m);
                                        object result = m.Invoke (target, invokeAttr, binder, args, culture);
                                        binder.ReorderArgumentArray (ref args, state);
                                        return result;
@@ -441,6 +471,11 @@ namespace System
                                if (m == null) {
                                        throwMissingFieldException = true;
                                } else {
+                                       ParameterInfo[] parameters = m.GetParameters();
+                                       bool hasParamArray = parameters.Length > 0 ? Attribute.IsDefined (parameters [parameters.Length - 1], 
+                                               typeof (ParamArrayAttribute)) : false;
+                                       if (hasParamArray)
+                                               ReorderParamArrayArguments (ref args, m);
                                        object result = m.Invoke (target, invokeAttr, binder, args, culture);
                                        binder.ReorderArgumentArray (ref args, state);
                                        return result;
@@ -607,6 +642,9 @@ namespace System
 
                private MethodBase CheckMethodSecurity (MethodBase mb)
                {
+#if NET_2_1
+                       return mb;
+#else
                        if (!SecurityManager.SecurityEnabled || (mb == null))
                                return mb;
 
@@ -617,6 +655,26 @@ namespace System
 
                        // this (unlike the Invoke step) is _and stays_ a LinkDemand (caller)
                        return SecurityManager.ReflectedLinkDemandQuery (mb) ? mb : null;
+#endif
+               }
+
+               void ReorderParamArrayArguments(ref object[] args, MethodBase method)
+               {
+                       ParameterInfo[] parameters = method.GetParameters();
+                       object[] newArgs = new object [parameters.Length];
+                       Array paramArray = Array.CreateInstance(parameters[parameters.Length - 1].ParameterType.GetElementType(), 
+                               args.Length - (parameters.Length - 1));
+                       int paramArrayCount = 0;
+                       for (int i = 0; i < args.Length; i++) {
+                               if (i < (parameters.Length - 1))
+                                       newArgs [i] = args [i];
+                               else {
+                                       paramArray.SetValue (args [i], paramArrayCount);
+                                       paramArrayCount ++;
+                               }
+                       }
+                       newArgs [parameters.Length - 1] = paramArray;
+                       args = newArgs;
                }
        }
 }