5 // Miguel de Icaza (miguel@ximian.com)
6 // Daniel Stodden (stodden@in.tum.de)
7 // Dietmar Maurer (dietmar@ximian.com)
9 // (C) Ximian, Inc. http://www.ximian.com
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Reflection;
36 using System.Runtime.Serialization;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
43 [ClassInterface (ClassInterfaceType.AutoDual)]
45 public abstract class Delegate : ICloneable, ISerializable
47 private Type target_type;
48 private object m_target;
49 private string method_name;
50 private IntPtr method_ptr;
51 private IntPtr delegate_trampoline;
52 private MethodInfo method_info;
54 protected Delegate (object target, string method)
57 throw new ArgumentNullException ("target");
60 throw new ArgumentNullException ("method");
62 this.target_type = null;
63 this.method_ptr = IntPtr.Zero;
64 this.m_target = target;
65 this.method_name = method;
68 protected Delegate (Type target, string method)
71 throw new ArgumentNullException ("target");
74 throw new ArgumentNullException ("method");
76 this.target_type = target;
77 this.method_ptr = IntPtr.Zero;
79 this.method_name = method;
82 public MethodInfo Method {
88 public object Target {
98 [MethodImplAttribute (MethodImplOptions.InternalCall)]
99 internal static extern Delegate CreateDelegate_internal (Type type, object target, MethodInfo info);
101 public static Delegate CreateDelegate (Type type, MethodInfo method)
104 throw new ArgumentNullException ("type");
107 throw new ArgumentNullException ("method");
109 if (!type.IsSubclassOf (typeof (MulticastDelegate)))
110 throw new ArgumentException ("type is not a subclass of Multicastdelegate");
112 if (!method.IsStatic)
113 throw new ArgumentException ("The method should be static.", "method");
115 ParameterInfo[] delargs = type.GetMethod ("Invoke").GetParameters ();
116 ParameterInfo[] args = method.GetParameters ();
118 if (args.Length != delargs.Length)
119 throw new ArgumentException ("method argument length mismatch");
121 int length = delargs.Length;
122 for (int i = 0; i < length; i++)
123 if (delargs [i].ParameterType != args [i].ParameterType)
124 throw new ArgumentException ("method arguments are incompatible");
126 return CreateDelegate_internal (type, null, method);
134 static Delegate CreateDelegate (Type type, object target, MethodInfo method)
137 throw new ArgumentNullException ("type");
140 throw new ArgumentNullException ("method");
142 if (!type.IsSubclassOf (typeof (MulticastDelegate)))
143 throw new ArgumentException ("type is not a subclass of Multicastdelegate");
145 return CreateDelegate_internal (type, target, method);
149 public static Delegate CreateDelegate (Type type, object target, string method)
151 return CreateDelegate(type, target, method, false);
154 public static Delegate CreateDelegate (Type type, Type target, string method)
157 throw new ArgumentNullException ("type");
160 throw new ArgumentNullException ("target");
163 throw new ArgumentNullException ("method");
165 if (!type.IsSubclassOf (typeof (MulticastDelegate)))
166 throw new ArgumentException ("type is not subclass of MulticastDelegate.");
168 ParameterInfo[] delargs = type.GetMethod ("Invoke").GetParameters ();
169 Type[] delargtypes = new Type [delargs.Length];
171 for (int i=0; i<delargs.Length; i++)
172 delargtypes [i] = delargs [i].ParameterType;
175 * FIXME: we should check the caller has reflection permission
176 * or if it lives in the same assembly...
178 BindingFlags flags = BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic;
179 MethodInfo info = target.GetMethod (method, flags, null, delargtypes, new ParameterModifier [0]);
182 throw new ArgumentException ("Couldn't bind to method.");
184 return CreateDelegate_internal (type, null, info);
187 public static Delegate CreateDelegate (Type type, object target, string method, bool ignoreCase)
190 throw new ArgumentNullException ("type");
193 throw new ArgumentNullException ("target");
196 throw new ArgumentNullException ("method");
198 if (!type.IsSubclassOf (typeof (MulticastDelegate)))
199 throw new ArgumentException ("type");
201 ParameterInfo[] delargs = type.GetMethod ("Invoke").GetParameters ();
202 Type[] delargtypes = new Type [delargs.Length];
204 for (int i=0; i<delargs.Length; i++)
205 delargtypes [i] = delargs [i].ParameterType;
208 * FIXME: we should check the caller has reflection permission
209 * or if it lives in the same assembly...
211 BindingFlags flags = BindingFlags.ExactBinding | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
214 flags |= BindingFlags.IgnoreCase;
216 MethodInfo info = target.GetType ().GetMethod (method, flags, null, delargtypes, new ParameterModifier [0]);
219 throw new ArgumentException ("Couldn't bind to method '" + method + "'.");
221 return CreateDelegate_internal (type, target, info);
224 public object DynamicInvoke (object[] args)
226 return DynamicInvokeImpl (args);
229 protected virtual object DynamicInvokeImpl (object[] args)
231 if (Method == null) {
232 Type[] mtypes = new Type [args.Length];
233 for (int i = 0; i < args.Length; ++i) {
234 mtypes [i] = args [i].GetType ();
236 method_info = m_target.GetType ().GetMethod (method_name, mtypes);
238 return Method.Invoke (m_target, args);
241 public virtual object Clone ()
243 return MemberwiseClone ();
246 public override bool Equals (object obj)
248 Delegate d = obj as Delegate;
253 // Do not compare method_ptr, since it can point to a trampoline
254 if ((d.target_type == target_type) && (d.m_target == m_target) &&
255 (d.method_name == method_name) && (d.method_info == method_info))
261 public override int GetHashCode ()
263 return (int)method_ptr;
266 protected virtual MethodInfo GetMethodImpl ()
271 // This is from ISerializable
272 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
274 DelegateSerializationHolder.GetDelegateData (this, info, context);
277 public virtual Delegate[] GetInvocationList()
279 return new Delegate[] { this };
283 /// Returns a new MulticastDelegate holding the
284 /// concatenated invocation lists of MulticastDelegates a and b
286 public static Delegate Combine (Delegate a, Delegate b)
296 if (a.GetType () != b.GetType ())
297 throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types."));
299 return a.CombineImpl (b);
303 /// Returns a new MulticastDelegate holding the
304 /// concatenated invocation lists of an Array of MulticastDelegates
306 public static Delegate Combine (Delegate[] delegates)
308 if (delegates == null)
311 Delegate retval = null;
313 foreach (Delegate next in delegates)
314 retval = Combine (retval, next);
319 protected virtual Delegate CombineImpl (Delegate d)
321 throw new MulticastNotSupportedException ("");
324 public static Delegate Remove (Delegate source, Delegate value)
329 return source.RemoveImpl (value);
332 protected virtual Delegate RemoveImpl (Delegate d)
340 public static Delegate RemoveAll (Delegate source, Delegate value)
342 Delegate tmp = source;
343 while ((source = Delegate.Remove (source, value)) != tmp)
349 public static bool operator == (Delegate a, Delegate b)
351 if ((object)a == null) {
352 if ((object)b == null)
355 } else if ((object) b == null)
361 public static bool operator != (Delegate a, Delegate b)