/* Contains the rarely used fields of Delegate */
sealed class DelegateData
{
- public static readonly DelegateData ClosedDelegateForStaticMethod = new DelegateData ();
-
public Type target_type;
public string method_name;
+ public bool curried_first_arg;
}
[ClassInterface (ClassInterfaceType.AutoDual)]
private object m_target;
private IntPtr method;
private IntPtr delegate_trampoline;
+ private IntPtr rgctx;
private IntPtr method_code;
private MethodInfo method_info;
private MethodInfo original_method_info;
private DelegateData data;
+
+ private bool method_is_virtual;
#pragma warning restore 169, 414, 649
#endregion
return method_info;
} else {
if (method != IntPtr.Zero) {
- method_info = (MethodInfo)MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (method));
+ if (!method_is_virtual)
+ method_info = (MethodInfo)MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (method));
+ else
+ method_info = GetVirtualMethod_internal ();
}
return method_info;
}
}
}
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ extern MethodInfo GetVirtualMethod_internal ();
+
public object Target {
get {
return m_target;
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern Delegate CreateDelegate_internal (Type type, object target, MethodInfo info, bool throwOnBindFailure);
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal extern void SetMulticastInvoke ();
-
private static bool arg_type_match (Type delArgType, Type argType) {
bool match = delArgType == argType;
MethodInfo invoke = type.GetMethod ("Invoke");
- if (!return_type_match (invoke.ReturnType, method.ReturnType))
+ if (!return_type_match (invoke.ReturnType, method.ReturnType)) {
if (throwOnBindFailure)
throw new ArgumentException ("method return type is incompatible");
else
return null;
+ }
ParameterInfo[] delargs = invoke.GetParametersInternal ();
ParameterInfo[] args = method.GetParametersInternal ();
argLengthMatch = args.Length == delargs.Length + 1;
}
}
- if (!argLengthMatch)
+ if (!argLengthMatch) {
if (throwOnBindFailure)
throw new ArgumentException ("method argument length mismatch");
else
return null;
+ }
bool argsMatch;
- DelegateData delegate_data = null;
+ DelegateData delegate_data = new DelegateData ();
if (target != null) {
if (!method.IsStatic) {
for (int i = 1; i < args.Length; i++)
argsMatch &= arg_type_match (delargs [i - 1].ParameterType, args [i].ParameterType);
- delegate_data = DelegateData.ClosedDelegateForStaticMethod;
+ delegate_data.curried_first_arg = true;
}
} else {
if (!method.IsStatic) {
for (int i = 0; i < delargs.Length; i++)
argsMatch &= arg_type_match (delargs [i].ParameterType, args [i + 1].ParameterType);
- delegate_data = DelegateData.ClosedDelegateForStaticMethod;
+ delegate_data.curried_first_arg = true;
} else {
argsMatch = true;
for (int i = 0; i < args.Length; i++)
}
}
- if (!argsMatch)
+ if (!argsMatch) {
if (throwOnBindFailure)
throw new ArgumentException ("method arguments are incompatible");
else
return null;
+ }
Delegate d = CreateDelegate_internal (type, target, method, throwOnBindFailure);
if (d != null)
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) {
}
var target = m_target;
+ if (this.data == null)
+ InitializeDelegateData ();
+
if (Method.IsStatic) {
//
// The delegate is bound to m_target
//
- if (data == DelegateData.ClosedDelegateForStaticMethod) {
+ if (data.curried_first_arg) {
if (args == null) {
args = new [] { target };
} else {
return MemberwiseClone ();
}
- internal bool Compare (Delegate d)
+ public override bool Equals (object obj)
{
+ Delegate d = obj as Delegate;
+
if (d == null)
return false;
-
+
// Do not compare method_ptr, since it can point to a trampoline
- if (d.m_target == m_target && d.method == method) {
+ if (d.m_target == m_target && d.Method == Method) {
if (d.data != null || data != null) {
/* 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;
}
return false;
}
- public override bool Equals (object obj)
- {
- return Compare (obj as Delegate);
- }
-
public override int GetHashCode ()
{
- return method.GetHashCode () ^ (m_target != null ? m_target.GetHashCode () : 0);
+ /* same implementation as CoreCLR */
+ return GetType ().GetHashCode ();
}
protected virtual MethodInfo GetMethodImpl ()
/// </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 RemotingServices.IsTransparentProxy (m_target);
#endif
}
+
+ internal static Delegate CreateDelegateNoSecurityCheck (RuntimeType type, Object firstArgument, MethodInfo method)
+ {
+ return CreateDelegate_internal (type, firstArgument, method, true);
+ }
+
+ /* Internal call largely inspired from MS Delegate.InternalAllocLike */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static MulticastDelegate AllocDelegateLike_internal (Delegate d);
}
}