Browse Source

in System:
2010-03-30 Jb Evain <[email protected]>

* MonoType.cs: let the binder reorder arguments when invoking
params methods.
* Activator.cs (CreateInstance): use BindToMethod instead of
SelectMethod to make sure that params constructors are properly called.

Fixes #591877

in System.Reflection:
2010-03-30 Jb Evain <[email protected]>

* Binder.cs: when invoking a params method, pack the params
arguments before doing the actual invocation.

Fixes #591877

svn path=/trunk/mcs/; revision=154449

Jb Evain 16 years ago
parent
commit
a322aeae23

+ 28 - 1
mcs/class/corlib/System.Reflection/Binder.cs

@@ -167,9 +167,36 @@ namespace System.Reflection
 				state = null;
 				if (names != null)
 					ReorderParameters (names, ref args, selected);
+
+				if (selected != null && args != null && args.Length > 0)
+					AdjustArguments (selected, ref args);
+
 				return selected;
 			}
 
+			static void AdjustArguments (MethodBase selected, ref object [] args)
+			{
+				var parameters = selected.GetParameters ();
+				if (parameters.Length == 0)
+					return;
+
+				var last_parameter = parameters [parameters.Length - 1];
+				if (!Attribute.IsDefined (last_parameter, typeof (ParamArrayAttribute)))
+					return;
+
+				var adjusted = new object [parameters.Length];
+				Array.Copy (args, adjusted, parameters.Length - 1);
+
+				var param_args_count = args.Length + 1 - parameters.Length;
+				var params_args = Array.CreateInstance (last_parameter.ParameterType.GetElementType (), param_args_count);
+
+				for (int i = 0; i < param_args_count; i++)
+					params_args.SetValue (args [args.Length - param_args_count + i], i);
+
+				adjusted [adjusted.Length - 1] = params_args;
+				args = adjusted;
+			}
+
 			void ReorderParameters (string [] names, ref object [] args, MethodBase selected)
 			{
 				object [] newArgs = new object [args.Length];
@@ -402,7 +429,7 @@ namespace System.Reflection
 				for (i = 0; i < match.Length; ++i) {
 					m = match [i];
 					ParameterInfo[] args = m.GetParameters ();
-					if (args.Length > types.Length)
+					if (args.Length > types.Length + 1)
 						continue;
 					else if (args.Length == 0)
 						continue;

+ 7 - 0
mcs/class/corlib/System.Reflection/ChangeLog

@@ -1,3 +1,10 @@
+2010-03-30  Jb Evain  <[email protected]>
+
+	* Binder.cs: when invoking a params method, pack the params
+	arguments before doing the actual invocation.
+
+	Fixes #591877
+
 2010-03-26 Rodrigo Kumpera  <[email protected]>
 
 	* Assembly.cs: Add IsDynamic.

+ 14 - 18
mcs/class/corlib/System/Activator.cs

@@ -253,34 +253,30 @@ namespace System
 			if ((bindingAttr & _accessFlags) == 0)
 				bindingAttr |= BindingFlags.Public | BindingFlags.Instance;
 
-			int length = 0;
-			if (args != null)
-				length = args.Length;
-
-			Type[] atypes = length == 0 ? Type.EmptyTypes : new Type [length];
-			for (int i = 0; i < length; ++i)
-				if (args [i] != null)
-					atypes [i] = args [i].GetType ();
-
 			if (binder == null)
 				binder = Binder.DefaultBinder;
 
-			ConstructorInfo ctor = (ConstructorInfo) binder.SelectMethod (bindingAttr, type.GetConstructors (bindingAttr), atypes, null);
+			object state;
+			ConstructorInfo ctor = (ConstructorInfo) binder.BindToMethod (bindingAttr, type.GetConstructors (bindingAttr), ref args, null, null, null, out state);
 
 			if (ctor == null) {
 				// Not sure about this
-				if (type.IsValueType && atypes.Length == 0) {
+				if (type.IsValueType && (args == null || args.Length == 0)) {
 					return CreateInstanceInternal (type);
 				}
 
-				StringBuilder sb = new StringBuilder ();
-				foreach (Type t in atypes){
-						sb.Append (t != null ? t.ToString () : "(unknown)");
-					sb.Append (", ");
+				var sb = new StringBuilder ();
+				if (args != null) {
+					for (int i = 0; i < args.Length; i++) {
+						if (i > 0)
+							sb.Append (", ");
+
+						var argument = args [i];
+						var arg_type = argument != null ? argument.GetType () : null;
+						sb.Append (arg_type != null ? arg_type.ToString () : "(unknown)");
+					}
 				}
-				if (sb.Length > 2)
-					sb.Length -= 2;
-				
+
 				throw new MissingMethodException (String.Format (Locale.GetText ("No constructor found for {0}::.ctor({1})"),
 										 type.FullName, sb));
 			}

+ 9 - 0
mcs/class/corlib/System/ChangeLog

@@ -1,3 +1,12 @@
+2010-03-30  Jb Evain  <[email protected]>
+
+	* MonoType.cs: let the binder reorder arguments when invoking
+	params methods.
+	* Activator.cs (CreateInstance): use BindToMethod instead of
+	SelectMethod to make sure that params constructors are properly called.
+
+	Fixes #591877
+
 2010-03-29  Carlos Alberto Cortez <[email protected]>
 
 	* TimeSpan.cs: Implement all the overloads of both TryParseExact and

+ 0 - 33
mcs/class/corlib/System/MonoType.cs

@@ -425,10 +425,6 @@ namespace System
 						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;
@@ -475,11 +471,6 @@ 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;
@@ -503,11 +494,6 @@ 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;
@@ -717,25 +703,6 @@ namespace System
 #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;
-		}
-
 #if NET_4_0
 		//seclevel { transparent = 0, safe-critical = 1, critical = 2}
 		[MethodImplAttribute(MethodImplOptions.InternalCall)]