// 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 Type target_type;
public string method_name;
+ public bool curried_first_arg;
}
[ClassInterface (ClassInterfaceType.AutoDual)]
return null;
bool argsMatch;
+ DelegateData delegate_data = new DelegateData ();
+
if (target != null) {
if (!method.IsStatic) {
argsMatch = arg_type_match_this (target.GetType (), method.DeclaringType, true);
} else {
argsMatch = arg_type_match (target.GetType (), args [0].ParameterType);
for (int i = 1; i < args.Length; i++)
- argsMatch &= arg_type_match (delargs [i - 1].ParameterType, args [i].ParameterType);
+ argsMatch &= arg_type_match (delargs [i - 1].ParameterType, args [i].ParameterType);
+
+ delegate_data.curried_first_arg = true;
}
} else {
if (!method.IsStatic) {
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.curried_first_arg = true;
} 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;
}
return DynamicInvokeImpl (args);
}
+ void InitializeDelegateData ()
+ {
+ DelegateData delegate_data = new DelegateData ();
+ if (method_info.IsStatic) {
+ if (m_target != null) {
+ delegate_data.curried_first_arg = true;
+ } else {
+ MethodInfo invoke = GetType ().GetMethod ("Invoke");
+ if (invoke.GetParametersCount () + 1 == method_info.GetParametersCount ())
+ delegate_data.curried_first_arg = true;
+ }
+ }
+ this.data = delegate_data;
+ }
+
protected virtual object DynamicInvokeImpl (object[] args)
{
if (Method == null) {
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 (this.data == null)
+ InitializeDelegateData ();
+
+ 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.curried_first_arg) {
+ 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 ()
/* Uncommon case */
if (d.data != null && data != null)
return (d.data.target_type == data.target_type && d.data.method_name == data.method_name);
- else
+ else {
+ if (d.data != null)
+ return d.data.target_type == null;
+ if (data != null)
+ return data.target_type == null;
return false;
+ }
}
return true;
}
/// </symmary>
public static Delegate Combine (Delegate a, Delegate b)
{
- if (a == null) {
- if (b == null)
- return null;
+ if (a == null)
return b;
- } else
- if (b == null)
- return a;
- if (a.GetType () != b.GetType ())
- throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types. First is {0} second is {1}.", a.GetType ().FullName, b.GetType ().FullName));
-
return a.CombineImpl (b);
}
return source;
if (source.GetType () != value.GetType ())
- throw new ArgumentException ("Delegate type mismatch");
+ throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types. First is {0} second is {1}.", source.GetType ().FullName, value.GetType ().FullName));
return source.RemoveImpl (value);
}
return RemotingServices.IsTransparentProxy (m_target);
#endif
}
+
+ internal static Delegate CreateDelegateNoSecurityCheck (RuntimeType type, Object firstArgument, MethodInfo method)
+ {
+ return CreateDelegate_internal (type, firstArgument, method, true);
+ }
}
}