// Miguel de Icaza (miguel@ximian.com)
// Daniel Stodden (stodden@in.tum.de)
// Dietmar Maurer (dietmar@ximian.com)
+// Marek Safar (marek.safar@gmail.com)
//
// (C) Ximian, Inc. http://www.ximian.com
-//
-
-//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright 2014 Xamarin, Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
namespace System
{
/* Contains the rarely used fields of Delegate */
- class DelegateData {
+ sealed class DelegateData
+ {
+ public static readonly DelegateData ClosedDelegateForStaticMethod = new DelegateData ();
+
public Type target_type;
public string method_name;
}
return null;
bool argsMatch;
+ DelegateData delegate_data = null;
+
if (target != null) {
if (!method.IsStatic) {
argsMatch = arg_type_match_this (target.GetType (), method.DeclaringType, true);
argsMatch = !(args [0].ParameterType.IsValueType || args [0].ParameterType.IsByRef) && allowClosed;
for (int i = 0; i < delargs.Length; i++)
argsMatch &= arg_type_match (delargs [i].ParameterType, args [i + 1].ParameterType);
+
+ delegate_data = DelegateData.ClosedDelegateForStaticMethod;
} else {
argsMatch = true;
for (int i = 0; i < args.Length; i++)
Delegate d = CreateDelegate_internal (type, target, method, throwOnBindFailure);
if (d != null)
d.original_method_info = method;
+ if (delegate_data != null)
+ d.data = delegate_data;
return d;
}
method_info = m_target.GetType ().GetMethod (data.method_name, mtypes);
}
- if (Method.IsStatic && (args != null ? args.Length : 0) == Method.GetParametersCount () - 1) {
+ var target = m_target;
+ if (Method.IsStatic) {
+ //
// The delegate is bound to m_target
- if (args != null) {
- object[] newArgs = new object [args.Length + 1];
- args.CopyTo (newArgs, 1);
- newArgs [0] = m_target;
- args = newArgs;
- } else {
- args = new object [] { m_target };
+ //
+ if (data == DelegateData.ClosedDelegateForStaticMethod) {
+ if (args == null) {
+ args = new [] { target };
+ } else {
+ Array.Resize (ref args, args.Length + 1);
+ Array.Copy (args, 0, args, 1, args.Length - 1);
+ args [0] = target;
+ }
+
+ target = null;
+ }
+ } else {
+ if (m_target == null && args != null && args.Length > 0) {
+ target = args [0];
+ Array.Copy (args, 1, args, 0, args.Length - 1);
+ Array.Resize (ref args, args.Length - 1);
}
- return Method.Invoke (null, args);
}
- return Method.Invoke (m_target, args);
+ return Method.Invoke (target, args);
}
public virtual object Clone ()
typeof (Action),
this.GetType ().GetMethod ("Banga"));
}
-#if !MONOTOUCH
+
[Test] // #664205
public void DynamicInvokeNullTarget ()
{
- var method = new DynamicMethod ("test", typeof (int), new [] { typeof (object) }, true);
- var il = method.GetILGenerator ();
- il.Emit (OpCodes.Ldc_I4, 42);
- il.Emit (OpCodes.Ret);
+ var d1 = Delegate.CreateDelegate (typeof(Func<int>), null, typeof(DelegateTest).GetMethod ("DynamicInvokeClosedStaticDelegate_CB"));
+ Assert.AreEqual (4, d1.DynamicInvoke ());
+ }
+
+ public static int DynamicInvokeClosedStaticDelegate_CB (object instance)
+ {
+ Assert.IsNull (instance);
+ return 4;
+ }
- var @delegate = method.CreateDelegate (typeof (Func<int>), null);
+ [Test]
+ public void DynamicInvokeOpenInstanceDelegate ()
+ {
+ var d1 = Delegate.CreateDelegate (typeof (Func<DelegateTest, int>), typeof(DelegateTest).GetMethod ("DynamicInvokeOpenInstanceDelegate_CB"));
+ Assert.AreEqual (5, d1.DynamicInvoke (new DelegateTest ()), "#1");
- Assert.AreEqual (42, (int) @delegate.DynamicInvoke ());
+ var d3 = (Func<DelegateTest, int>) d1;
+ Assert.AreEqual (5, d3 (null), "#2");
}
-#endif
+
+ public int DynamicInvokeOpenInstanceDelegate_CB ()
+ {
+ return 5;
+ }
+
+ [Test]
+ public void DynamicInvoke_InvalidArguments ()
+ {
+ Delegate d = new Func<int, int> (TestMethod);
+
+ try {
+ d.DynamicInvoke (null);
+ Assert.Fail ("#1");
+ } catch (TargetParameterCountException) {
+ }
+
+ try {
+ d.DynamicInvoke (new object [0]);
+ Assert.Fail ("#2");
+ } catch (TargetParameterCountException) {
+ }
+ }
+
+ public static int TestMethod (int i)
+ {
+ throw new NotSupportedException ();
+ }
+
#endif
public static void CreateDelegateOfStaticMethodBoundToNull_Helper (object[] args) {}
} catch (ArgumentException) {}
}
- private static Func<Int32, Int32, bool> Int32D = (x, y) => (x & y) == y;
+ private static Func<Int32, Int32, bool> Int32D = (x, y) => (x & y) == y;
[Test]
public void EnumBaseTypeConversion () {