X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem%2FDelegate.cs;h=733eac9a4d3f132eab175fecdeed571364b4145f;hb=0717f141b92db56481cc09af70c026d7ffad8921;hp=774aade3a1a40d9955bfcdd27195d53f1351f686;hpb=dbf19eb41dbd299c4c33d4de35ffe3cf6c669832;p=mono.git diff --git a/mcs/class/corlib/System/Delegate.cs b/mcs/class/corlib/System/Delegate.cs index 774aade3a1a..733eac9a4d3 100644 --- a/mcs/class/corlib/System/Delegate.cs +++ b/mcs/class/corlib/System/Delegate.cs @@ -33,24 +33,42 @@ // 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 + [System.Runtime.InteropServices.ComVisible (true)] + [Serializable] public abstract class Delegate : ICloneable, ISerializable { - private Type target_type; - private object m_target; - private string method_name; + #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 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 (target == null) @@ -59,10 +77,9 @@ namespace System 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) @@ -73,15 +90,21 @@ namespace System 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 { get { - return method_info; + if (method_info != null) { + return method_info; + } else { + if (method != IntPtr.Zero) { + method_info = (MethodInfo)MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (method)); + } + return method_info; + } } } @@ -96,10 +119,40 @@ namespace System // [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; + + // Delegate contravariance + if (!match) { + if (!argType.IsValueType && argType.IsAssignableFrom (delArgType)) + match = true; + } + + return match; + } + + private static bool return_type_match (Type delReturnType, Type returnType) { + bool returnMatch = returnType == delReturnType; + + if (!returnMatch) { + // Delegate covariance + if (!returnType.IsValueType && delReturnType.IsAssignableFrom (returnType)) + returnMatch = true; + } + + return returnMatch; + } - public static Delegate CreateDelegate (Type type, MethodInfo method) + public static Delegate CreateDelegate (Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure) { + // The name of the parameter changed in 2.0 + object target = firstArgument; + if (type == null) throw new ArgumentNullException ("type"); @@ -109,94 +162,122 @@ namespace System if (!type.IsSubclassOf (typeof (MulticastDelegate))) throw new ArgumentException ("type is not a subclass of Multicastdelegate"); - if (!method.IsStatic) - throw new ArgumentException ("The method should be static.", "method"); - MethodInfo invoke = type.GetMethod ("Invoke"); - // FIXME: Check the return type on the 1.0 profile as well -#if NET_2_0 - Type returnType = method.ReturnType; - Type delReturnType = invoke.ReturnType; - bool returnMatch = returnType == delReturnType; - - if (!returnMatch) { - // Delegate covariance - if (!delReturnType.IsValueType && (delReturnType != typeof (ValueType)) && (delReturnType.IsAssignableFrom (returnType))) - returnMatch = true; - } - - if (!returnMatch) - throw new ArgumentException ("method return type is incompatible"); -#endif + if (!return_type_match (invoke.ReturnType, method.ReturnType)) + if (throwOnBindFailure) + throw new ArgumentException ("method return type is incompatible"); + else + return null; ParameterInfo[] delargs = invoke.GetParameters (); ParameterInfo[] args = method.GetParameters (); - if (args.Length != delargs.Length) - throw new ArgumentException ("method argument length mismatch"); - - int length = delargs.Length; - for (int i = 0; i < length; i++) { - bool match = delargs [i].ParameterType == args [i].ParameterType; - -#if NET_2_0 - // Delegate contravariance - if (!match) { - Type argType = delargs [i].ParameterType; + bool argLengthMatch; + + if (target != null) { + // delegate closed over target + if (!method.IsStatic) + // target is passed as this + argLengthMatch = (args.Length == delargs.Length); + else + // target is passed as the first argument to the static method + argLengthMatch = (args.Length == delargs.Length + 1); + } else { + if (!method.IsStatic) + // + // Net 2.0 feature. The first argument of the delegate is passed + // as the 'this' argument to the method. + // + argLengthMatch = (args.Length + 1 == delargs.Length); + else { + argLengthMatch = (args.Length == delargs.Length); + + if (!argLengthMatch) + // closed over a null reference + argLengthMatch = args.Length == delargs.Length + 1; + } + } + if (!argLengthMatch) + if (throwOnBindFailure) + throw new ArgumentException ("method argument length mismatch"); + else + return null; - if (!argType.IsValueType && (argType != typeof (ValueType)) && (args [i].ParameterType.IsAssignableFrom (argType))) - match = true; + bool argsMatch; + if (target != null) { + if (!method.IsStatic) { + argsMatch = arg_type_match (target.GetType (), method.DeclaringType); + for (int i = 0; i < args.Length; i++) + argsMatch &= arg_type_match (delargs [i].ParameterType, args [i].ParameterType); + } 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); + } + } else { + if (!method.IsStatic) { + // The first argument should match this + argsMatch = arg_type_match (delargs [0].ParameterType, method.DeclaringType); + for (int i = 0; i < args.Length; i++) + argsMatch &= arg_type_match (delargs [i + 1].ParameterType, args [i].ParameterType); + } else { + 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); + } } -#endif + } - if (!match) + if (!argsMatch) + if (throwOnBindFailure) throw new ArgumentException ("method arguments are incompatible"); - } + else + return null; - return CreateDelegate_internal (type, null, 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) - { - if (type == null) - throw new ArgumentNullException ("type"); - - if (method == null) - throw new ArgumentNullException ("method"); - - if (!type.IsSubclassOf (typeof (MulticastDelegate))) - throw new ArgumentException ("type is not a subclass of Multicastdelegate"); + public static Delegate CreateDelegate (Type type, object firstArgument, MethodInfo method) { + return CreateDelegate (type, firstArgument, method, true); + } - return CreateDelegate_internal (type, target, method); + public static Delegate CreateDelegate (Type type, MethodInfo method, bool throwOnBindFailure) + { + return CreateDelegate (type, null, method, throwOnBindFailure); + } + public static Delegate CreateDelegate (Type type, MethodInfo method) { + return CreateDelegate (type, method, true); } - + public static Delegate CreateDelegate (Type type, object target, string method) { return CreateDelegate(type, target, method, false); } - public static Delegate CreateDelegate (Type type, Type target, string method) + static MethodInfo GetCandidateMethod (Type type, Type target, string method, BindingFlags bflags, bool ignoreCase, bool throwOnBindFailure) { if (type == null) throw new ArgumentNullException ("type"); - if (target == null) - throw new ArgumentNullException ("target"); - if (method == null) throw new ArgumentNullException ("method"); if (!type.IsSubclassOf (typeof (MulticastDelegate))) throw new ArgumentException ("type is not subclass of MulticastDelegate."); - ParameterInfo[] delargs = type.GetMethod ("Invoke").GetParameters (); + MethodInfo invoke = type.GetMethod ("Invoke"); + ParameterInfo [] delargs = invoke.GetParameters (); Type[] delargtypes = new Type [delargs.Length]; for (int i=0; i - public static Delegate Combine (Delegate[] delegates) + [System.Runtime.InteropServices.ComVisible (true)] + public static Delegate Combine (params Delegate[] delegates) { if (delegates == null) return null; @@ -366,7 +478,7 @@ namespace System protected virtual Delegate CombineImpl (Delegate d) { - throw new MulticastNotSupportedException (""); + throw new MulticastNotSupportedException (String.Empty); } public static Delegate Remove (Delegate source, Delegate value) @@ -384,7 +496,7 @@ namespace System return this; } -#if NET_1_1 + public static Delegate RemoveAll (Delegate source, Delegate value) { Delegate tmp = source; @@ -393,22 +505,27 @@ namespace System 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); } } }