//
using System.Reflection;
+using System.Runtime.Remoting;
using System.Runtime.Serialization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System
{
-#if NET_1_1
+ /* Contains the rarely used fields of Delegate */
+ class DelegateData {
+ public Type target_type;
+ public string method_name;
+ }
+
[ClassInterface (ClassInterfaceType.AutoDual)]
-#endif
-#if NET_2_0
[System.Runtime.InteropServices.ComVisible (true)]
[Serializable]
-#endif
public abstract class Delegate : ICloneable, ISerializable
{
#region Sync with object-internals.h
+#pragma warning disable 169, 414, 649
private IntPtr method_ptr;
private IntPtr invoke_impl;
private object m_target;
private IntPtr method;
- private Type target_type;
- private string method_name;
private IntPtr delegate_trampoline;
+ private IntPtr method_code;
private MethodInfo method_info;
// Keep a ref of the MethodInfo passed to CreateDelegate.
// Used to keep DynamicMethods alive.
private MethodInfo original_method_info;
+
+ private DelegateData data;
+#pragma warning restore 169, 414, 649
#endregion
protected Delegate (object target, string method)
if (method == null)
throw new ArgumentNullException ("method");
- this.target_type = null;
- this.method_ptr = IntPtr.Zero;
this.m_target = target;
- this.method_name = method;
+ this.data = new DelegateData ();
+ this.data.method_name = method;
}
protected Delegate (Type target, string method)
if (method == null)
throw new ArgumentNullException ("method");
- this.target_type = target;
- this.method_ptr = IntPtr.Zero;
- this.m_target = null;
- this.method_name = method;
+ this.data = new DelegateData ();
+ this.data.method_name = method;
+ this.data.target_type = target;
}
public MethodInfo Method {
if (method_info != null) {
return method_info;
} else {
- if (method != IntPtr.Zero)
- method_info = (MethodInfo)MethodBase.GetMethodFromHandle (new RuntimeMethodHandle (method));
+ if (method != IntPtr.Zero) {
+ method_info = (MethodInfo)MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (method));
+ }
return method_info;
}
}
//
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal static extern Delegate CreateDelegate_internal (Type type, object target, MethodInfo info);
+ 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;
-#if NET_2_0
// Delegate contravariance
if (!match) {
- if (!delArgType.IsValueType && (delArgType != typeof (ValueType)) && (argType.IsAssignableFrom (delArgType)))
+ if (!argType.IsValueType && argType.IsAssignableFrom (delArgType))
match = true;
}
-#endif
+
return match;
}
private static bool return_type_match (Type delReturnType, Type returnType) {
bool returnMatch = returnType == delReturnType;
-#if NET_2_0
if (!returnMatch) {
// Delegate covariance
- if (!delReturnType.IsValueType && (delReturnType != typeof (ValueType)) && (delReturnType.IsAssignableFrom (returnType)))
+ if (!returnType.IsValueType && delReturnType.IsAssignableFrom (returnType))
returnMatch = true;
}
-#endif
return returnMatch;
}
-#if NET_2_0
public static Delegate CreateDelegate (Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
-#else
- internal static Delegate CreateDelegate (Type type, object target, MethodInfo method, bool throwOnBindFailure)
-#endif
{
-#if NET_2_0
// The name of the parameter changed in 2.0
object target = firstArgument;
-#endif
if (type == null)
throw new ArgumentNullException ("type");
if (!type.IsSubclassOf (typeof (MulticastDelegate)))
throw new ArgumentException ("type is not a subclass of Multicastdelegate");
-#if !NET_2_0
- if ((target == null) && !method.IsStatic) {
- if (throwOnBindFailure)
- throw new ArgumentException ("The method should be static.", "method");
- else
- return null;
- }
-#endif
MethodInfo invoke = type.GetMethod ("Invoke");
else
return null;
- // FIXME: Figure out how net 1.1 works
-#if NET_2_0
ParameterInfo[] delargs = invoke.GetParameters ();
ParameterInfo[] args = method.GetParameters ();
// as the 'this' argument to the method.
//
argLengthMatch = (args.Length + 1 == delargs.Length);
- else
+ else {
argLengthMatch = (args.Length == delargs.Length);
+
+ if (!argLengthMatch)
+ // closed over a null reference
+ argLengthMatch = args.Length == delargs.Length + 1;
+ }
}
if (!argLengthMatch)
if (throwOnBindFailure)
for (int i = 0; i < args.Length; i++)
argsMatch &= arg_type_match (delargs [i + 1].ParameterType, args [i].ParameterType);
} else {
- argsMatch = true;
- for (int i = 0; i < args.Length; i++)
- argsMatch &= arg_type_match (delargs [i].ParameterType, args [i].ParameterType);
+ if (delargs.Length + 1 == args.Length) {
+ // closed over a null reference
+ argsMatch = !args [0].ParameterType.IsValueType;
+ for (int i = 0; i < delargs.Length; i++)
+ argsMatch &= arg_type_match (delargs [i].ParameterType, args [i + 1].ParameterType);
+ } else {
+ argsMatch = true;
+ for (int i = 0; i < args.Length; i++)
+ argsMatch &= arg_type_match (delargs [i].ParameterType, args [i].ParameterType);
+ }
}
}
throw new ArgumentException ("method arguments are incompatible");
else
return null;
-#endif
- Delegate d = CreateDelegate_internal (type, target, method);
- d.original_method_info = method;
+ Delegate d = CreateDelegate_internal (type, target, method, throwOnBindFailure);
+ if (d != null)
+ d.original_method_info = method;
return d;
}
-#if NET_2_0
- public
-#else
- internal
-#endif
- static Delegate CreateDelegate (Type type, object target, MethodInfo method) {
- return CreateDelegate (type, target, method, true);
+ public static Delegate CreateDelegate (Type type, object firstArgument, MethodInfo method) {
+ return CreateDelegate (type, firstArgument, method, true);
}
-#if NET_2_0
- public
-#else
- internal
-#endif
- static Delegate CreateDelegate (Type type, MethodInfo method, bool throwOnBindFailure)
+ public static Delegate CreateDelegate (Type type, MethodInfo method, bool throwOnBindFailure)
{
return CreateDelegate (type, null, method, throwOnBindFailure);
}
return info;
}
-#if NET_2_0
- public
-#else
- internal
-#endif
- static Delegate CreateDelegate (Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
+ public static Delegate CreateDelegate (Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
{
if (target == null)
throw new ArgumentNullException ("target");
if (info == null)
return null;
- return CreateDelegate_internal (type, null, info);
+ return CreateDelegate_internal (type, null, info, throwOnBindFailure);
}
public static Delegate CreateDelegate (Type type, Type target, string method) {
return CreateDelegate (type, target, method, false, true);
}
-#if NET_2_0
public static Delegate CreateDelegate (Type type, Type target, string method, bool ignoreCase) {
return CreateDelegate (type, target, method, ignoreCase, true);
}
-#endif
-#if NET_2_0
- public
-#else
- internal
-#endif
- static Delegate CreateDelegate (Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
+ public static Delegate CreateDelegate (Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
{
if (target == null)
throw new ArgumentNullException ("target");
if (info == null)
return null;
- return CreateDelegate_internal (type, target, info);
+ return CreateDelegate_internal (type, target, info, throwOnBindFailure);
}
public static Delegate CreateDelegate (Type type, object target, string method, bool ignoreCase) {
return CreateDelegate (type, target, method, ignoreCase, true);
}
-#if NET_2_0
public object DynamicInvoke (params object[] args)
-#else
- public object DynamicInvoke (object[] args)
-#endif
{
return DynamicInvokeImpl (args);
}
for (int i = 0; i < args.Length; ++i) {
mtypes [i] = args [i].GetType ();
}
- method_info = m_target.GetType ().GetMethod (method_name, mtypes);
+ method_info = m_target.GetType ().GetMethod (data.method_name, mtypes);
}
-#if NET_2_0
if ((m_target != null) && Method.IsStatic) {
// The delegate is bound to m_target
if (args != null) {
}
return Method.Invoke (null, args);
}
-#endif
return Method.Invoke (m_target, args);
}
return false;
// Do not compare method_ptr, since it can point to a trampoline
- if ((d.target_type == target_type) && (d.m_target == m_target) &&
- (d.method_name == method_name) && (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
+ return false;
+ }
return true;
+ }
return false;
}
public override int GetHashCode ()
{
- // FIXME: Sync with Equals above
- return (int)method_ptr;
+ return method.GetHashCode () ^ (m_target != null ? m_target.GetHashCode () : 0);
}
protected virtual MethodInfo GetMethodImpl ()
/// Returns a new MulticastDelegate holding the
/// concatenated invocation lists of an Array of MulticastDelegates
/// </symmary>
-#if NET_2_0
[System.Runtime.InteropServices.ComVisible (true)]
public static Delegate Combine (params Delegate[] delegates)
-#else
- public static Delegate Combine (Delegate[] delegates)
-#endif
{
if (delegates == null)
return null;
return this;
}
-#if NET_1_1
+
public static Delegate RemoveAll (Delegate source, Delegate value)
{
Delegate tmp = source;
return tmp;
}
-#endif
- public static bool operator == (Delegate a, Delegate b)
+
+ public static bool operator == (Delegate d1, Delegate d2)
{
- if ((object)a == null) {
- if ((object)b == null)
+ if ((object)d1 == null) {
+ if ((object)d2 == null)
return true;
return false;
- } else if ((object) b == null)
+ } else if ((object) d2 == null)
return false;
- return a.Equals (b);
+ return d1.Equals (d2);
+ }
+
+ public static bool operator != (Delegate d1, Delegate d2)
+ {
+ return !(d1 == d2);
}
- public static bool operator != (Delegate a, Delegate b)
+ internal bool IsTransparentProxy ()
{
- return !(a == b);
+ return RemotingServices.IsTransparentProxy (m_target);
}
}
}