2002-08-07 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mcs / class / corlib / System / Delegate.cs
1 //
2 // System.Delegate.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Daniel Stodden (stodden@in.tum.de)
7 //   Dietmar Maurer (dietmar@ximian.com)
8 //
9 // (C) Ximian, Inc.  http://www.ximian.com
10 //
11
12 using System;
13 using System.Globalization;
14 using System.Reflection;
15 using System.Runtime.Serialization;
16 using System.Runtime.CompilerServices;
17
18
19 namespace System {
20
21         [MonoTODO]
22         public abstract class Delegate : ICloneable, ISerializable {
23                 protected Type target_type;
24                 protected object m_target;
25                 protected string method_name;
26                 protected IntPtr method_ptr;
27                 protected IntPtr delegate_trampoline;
28                 protected MethodInfo method_info;
29
30                 protected Delegate (object target, string method)
31                 {
32                         if (target == null)
33                                 throw new ArgumentNullException (Locale.GetText ("Target object is null"));
34
35                         if (method == null)
36                                 throw new ArgumentNullException (Locale.GetText ("method name is null"));
37
38                         this.target_type = null;
39                         this.method_ptr = IntPtr.Zero;
40                         this.m_target = target;
41                         this.method_name = method;
42                 }
43
44                 protected Delegate (Type target_type, string method)
45                 {
46                         if (m_target == null)
47                                 throw new ArgumentNullException (Locale.GetText ("Target type is null"));
48
49                         if (method == null)
50                                 throw new ArgumentNullException (Locale.GetText ("method string is null"));
51
52                         this.target_type = target_type;
53                         this.method_ptr = IntPtr.Zero;
54                         this.m_target = null;
55                         this.method_name = method;
56                 }
57
58                 public MethodInfo Method {
59                         get {
60                                 return method_info;
61                         }
62                 }
63
64                 public object Target {
65                         get {
66                                 return m_target;
67                         }
68                 }
69
70                 //
71                 // Methods
72                 //
73
74                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
75                 internal static extern Delegate CreateDelegate_internal (Type type, object target, MethodInfo info);
76
77                 [MonoTODO]
78                 public static Delegate CreateDelegate (Type type, MethodInfo info)
79                 {
80                         if (type == null)
81                                 throw new ArgumentNullException (Locale.GetText ("Type is null"));
82
83                         if (info == null)
84                                 throw new ArgumentNullException (Locale.GetText ("MethodInfo is null"));
85
86                         return CreateDelegate_internal (type, null, info);
87                 }
88                 
89                 [MonoTODO]
90                 public static Delegate CreateDelegate (Type type, object target, string method)
91                 {
92                         if (type == null)
93                                 throw new ArgumentNullException (Locale.GetText ("Type is null"));
94
95                         if (target == null)
96                                 throw new ArgumentNullException (Locale.GetText ("Target object is null"));
97
98                         if (method == null)
99                                 throw new ArgumentNullException (Locale.GetText ("method string is null"));
100
101                         BindingFlags flags =  BindingFlags.Public | BindingFlags.Instance;
102                         MethodInfo info = target.GetType ().GetMethod (method, flags);
103                         return CreateDelegate_internal (type, target, info);
104                 }
105
106                 [MonoTODO]
107                 public static Delegate CreateDelegate (Type type, Type target, string method)
108                 {
109                         if (type == null)
110                                 throw new ArgumentNullException (Locale.GetText ("Type is null"));
111
112                         if (target == null)
113                                 throw new ArgumentNullException (Locale.GetText ("Target type is null"));
114
115                         if (method == null)
116                                 throw new ArgumentNullException (Locale.GetText ("method string is null"));
117
118                         BindingFlags flags =  BindingFlags.Public | BindingFlags.Static;
119                         MethodInfo info = target.GetMethod (method, flags);
120                         return CreateDelegate_internal (type, null, info);
121                 }
122
123                 [MonoTODO]
124                 public static Delegate CreateDelegate (Type type, object target, string method, bool ignorecase)
125                 {
126                         if (type == null)
127                                 throw new ArgumentNullException (Locale.GetText ("Type is null"));
128
129                         if (target == null)
130                                 throw new ArgumentNullException (Locale.GetText ("Target object is null"));
131
132                         if (method == null)
133                                 throw new ArgumentNullException (Locale.GetText ("method string is null"));
134                         
135                         Type target_type = target.GetType ();
136                         BindingFlags flags =  BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase;
137                         MethodInfo info = target_type.GetMethod (method, flags);
138                         return CreateDelegate_internal (type, target, info);                    
139                 }
140
141                 public object DynamicInvoke( object[] args )
142                 {
143                         return DynamicInvokeImpl( args );
144                 }
145
146                 public virtual object DynamicInvokeImpl( object[] args )
147                 {
148                         if (Method == null) {
149                                 Type[] mtypes = new Type [args.Length];
150                                 for (int i = 0; i < args.Length; ++i) {
151                                 mtypes [i] = args [i].GetType ();
152                         }
153                                 method_info = m_target.GetType ().GetMethod (method_name, mtypes);
154                         }
155                         return Method.Invoke( m_target, args );
156                 }
157
158                 public virtual object Clone()
159                 {
160                         return MemberwiseClone();
161                 }
162
163                 public override bool Equals (object o)
164                 {
165                         if ( o == null )
166                                 return false;
167                         
168                         if ( o.GetType() != this.GetType() )
169                                 return false;
170
171                         Delegate d = (Delegate) o;
172                         if ((d.target_type == target_type) &&
173                             (d.m_target == m_target) &&
174                             (d.method_name == method_name) &&
175                             (d.method_ptr == method_ptr))
176                                 return true;
177
178                         return false;
179                 }
180
181                 public override int GetHashCode ()
182                 {
183                         return (int)method_ptr;
184                 }
185
186                 // This is from ISerializable
187                 [MonoTODO]
188                 public void GetObjectData (SerializationInfo info, StreamingContext context)
189                 {
190                         // TODO: IMPLEMENT ME
191                 }
192
193                 public virtual Delegate[] GetInvocationList()
194                 {
195                         return new Delegate[] { this };
196                 }
197
198                 /// <symmary>
199                 ///   Returns a new MulticastDelegate holding the
200                 ///   concatenated invocation lists of MulticastDelegates a and b
201                 /// </symmary>
202                 public static Delegate Combine (Delegate a, Delegate b)
203                 {
204                         if (a == null){
205                                 if (b == null)
206                                         return null;
207                                 return b;
208                         } else 
209                                 if (b == null)
210                                         return a;
211
212                         if (a.GetType () != b.GetType ())
213                                 throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types"));
214                         
215                         return a.CombineImpl (b);
216                 }
217
218                 /// <symmary>
219                 ///   Returns a new MulticastDelegate holding the
220                 ///   concatenated invocation lists of an Array of MulticastDelegates
221                 /// </symmary>
222                 public static Delegate Combine( Delegate[] delegates )
223                 {
224                         Delegate retval = null;
225
226                         foreach ( Delegate next in delegates )
227                                 retval = Combine( retval, next );
228
229                         return retval;
230                 }
231
232
233                 protected virtual Delegate CombineImpl (Delegate d)
234                 {
235                         throw new MulticastNotSupportedException ("");
236                 }
237                 
238                 
239                 public static Delegate Remove( Delegate source, Delegate value ) 
240                 {
241                         if ( source == null )
242                                 return null;
243                                 
244                         return source.RemoveImpl( value );
245                 }
246
247                 protected virtual Delegate RemoveImpl( Delegate d )
248                 {
249                         if ( this.Equals( d ) )
250                                 return null;
251                        
252                         return this;
253                 }
254
255                 public static bool operator ==( Delegate a, Delegate b )
256                 {
257                         if ((object)a == null) {
258                                 if ((object)b == null)
259                                         return true;
260                                 return false;
261                         }
262                         return a.Equals( b );
263                 }
264
265                 public static bool operator !=( Delegate a, Delegate b )
266                 {
267                         return !(a == b);
268                 }
269         }
270 }