2008-03-31 Mark Probst <mark.probst@gmail.com>
[mono.git] / mcs / class / corlib / System.Reflection / MonoMethod.cs
1 //
2 // System.Reflection/MonoMethod.cs
3 // The class used to represent methods from the mono runtime.
4 //
5 // Author:
6 //   Paolo Molaro (lupus@ximian.com)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Globalization;
32 using System.Runtime.CompilerServices;
33 using System.Runtime.InteropServices;
34 using System.Runtime.Serialization;
35 using System.Reflection.Emit;
36 using System.Security;
37 using System.Threading;
38 using System.Text;
39
40
41 namespace System.Reflection {
42         
43         internal struct MonoMethodInfo 
44         {
45                 internal Type parent;
46                 internal Type ret;
47                 internal MethodAttributes attrs;
48                 internal MethodImplAttributes iattrs;
49                 internal CallingConventions callconv;
50
51                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
52                 internal static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
53                 
54                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
55                 internal static extern ParameterInfo[] get_parameter_info (IntPtr handle);
56
57                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58                 internal static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
59         };
60         
61         /*
62          * Note: most of this class needs to be duplicated for the contructor, since
63          * the .NET reflection class hierarchy is so broken.
64          */
65         [Serializable()]
66         internal class MonoMethod : MethodInfo, ISerializable
67         {
68                 internal IntPtr mhandle;
69                 string name;
70                 Type reftype;
71
72                 internal MonoMethod () {
73                 }
74
75                 internal MonoMethod (RuntimeMethodHandle mhandle) {
76                         this.mhandle = mhandle.Value;
77                 }
78                 
79                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
80                 internal static extern string get_name (MethodBase method);
81
82                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
83                 internal static extern MonoMethod get_base_definition (MonoMethod method);
84
85                 public override MethodInfo GetBaseDefinition ()
86                 {
87                         return get_base_definition (this);
88                 }
89
90 #if NET_2_0 || BOOTSTRAP_NET_2_0
91                 public override ParameterInfo ReturnParameter {
92                         get {
93                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
94                         }
95                 }
96 #endif
97
98                 public override Type ReturnType {
99                         get {
100                                 MonoMethodInfo info;
101                                 MonoMethodInfo.get_method_info (mhandle, out info);
102                                 return info.ret;
103                         }
104                 }
105                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
106                         get {
107                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
108                         }
109                 }
110                 
111                 public override MethodImplAttributes GetMethodImplementationFlags() {
112                         MonoMethodInfo info;
113                         MonoMethodInfo.get_method_info (mhandle, out info);
114                         return info.iattrs;
115                 }
116
117                 public override ParameterInfo[] GetParameters() {
118                         return MonoMethodInfo.get_parameter_info (mhandle);
119                 }
120
121                 /*
122                  * InternalInvoke() receives the parameters correctly converted by the 
123                  * binder to match the types of the method signature.
124                  */
125                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
126                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
127                 
128                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
129                 {
130                         if (binder == null)
131                                 binder = Binder.DefaultBinder;
132                         ParameterInfo[] pinfo = GetParameters ();
133                         if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
134                                 throw new ArgumentException ("parameters");
135
136 #if !NET_2_1
137                         if (SecurityManager.SecurityEnabled) {
138                                 // sadly Attributes doesn't tell us which kind of security action this is so
139                                 // we must do it the hard way - and it also means that we can skip calling
140                                 // Attribute (which is another an icall)
141                                 SecurityManager.ReflectedLinkDemandInvoke (this);
142                         }
143 #endif
144
145 #if NET_2_0
146                         if (ContainsGenericParameters)
147                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
148 #endif
149
150                         Exception exc;
151                         object o = null;
152
153                         try {
154                                 // The ex argument is used to distinguish exceptions thrown by the icall
155                                 // from the exceptions thrown by the called method (which need to be
156                                 // wrapped in TargetInvocationException).
157                                 o = InternalInvoke (obj, parameters, out exc);
158 #if NET_2_0
159                         } catch (ThreadAbortException) {
160                                 throw;
161 #endif
162 #if NET_2_1
163                         } catch (MethodAccessException) {
164                                 throw;
165 #endif
166                         } catch (Exception e) {
167                                 throw new TargetInvocationException (e);
168                         }
169
170                         if (exc != null)
171                                 throw exc;
172                         return o;
173                 }
174
175                 public override RuntimeMethodHandle MethodHandle { 
176                         get {return new RuntimeMethodHandle (mhandle);} 
177                 }
178                 public override MethodAttributes Attributes { 
179                         get {
180                                 MonoMethodInfo info;
181                                 MonoMethodInfo.get_method_info (mhandle, out info);
182                                 return info.attrs;
183                         } 
184                 }
185
186                 public override CallingConventions CallingConvention { 
187                         get {
188                                 MonoMethodInfo info;
189                                 MonoMethodInfo.get_method_info (mhandle, out info);
190                                 return info.callconv;
191                         }
192                 }
193                 
194                 public override Type ReflectedType {
195                         get {
196                                 return reftype;
197                         }
198                 }
199                 public override Type DeclaringType {
200                         get {
201                                 MonoMethodInfo info;
202                                 MonoMethodInfo.get_method_info (mhandle, out info);
203                                 return info.parent;
204                         }
205                 }
206                 public override string Name {
207                         get {
208                                 if (name != null)
209                                         return name;
210                                 return get_name (this);
211                         }
212                 }
213                 
214                 public override bool IsDefined (Type attributeType, bool inherit) {
215                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
216                 }
217
218                 public override object[] GetCustomAttributes( bool inherit) {
219                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
220                 }
221                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
222                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
223                 }
224
225                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
226                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
227
228                 internal object[] GetPseudoCustomAttributes ()
229                 {
230                         int count = 0;
231
232                         /* MS.NET doesn't report MethodImplAttribute */
233
234                         MonoMethodInfo info;
235                         MonoMethodInfo.get_method_info (mhandle, out info);
236                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
237                                 count ++;
238                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
239                                 count ++;
240                         
241                         if (count == 0)
242                                 return null;
243                         object[] attrs = new object [count];
244                         count = 0;
245
246                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
247                                 attrs [count ++] = new PreserveSigAttribute ();
248                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
249                                 DllImportAttribute attr = GetDllImportAttribute (mhandle);
250                                 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
251                                         attr.PreserveSig = true;
252                                 attrs [count ++] = attr;
253                         }
254
255                         return attrs;
256                 }
257
258                 public override string ToString () {
259                         StringBuilder sb = new StringBuilder ();
260                         if (ReturnType.IsClass)
261                                 sb.Append (ReturnType.ToString ());
262                         else
263                                 sb.Append (ReturnType.Name);
264                         sb.Append (" ");
265                         sb.Append (Name);
266 #if NET_2_0 || BOOTSTRAP_NET_2_0
267                         if (IsGenericMethod) {
268                                 Type[] gen_params = GetGenericArguments ();
269                                 sb.Append ("[");
270                                 for (int j = 0; j < gen_params.Length; j++) {
271                                         if (j > 0)
272                                                 sb.Append (",");
273                                         sb.Append (gen_params [j].Name);
274                                 }
275                                 sb.Append ("]");
276                         }
277 #endif
278                         sb.Append ("(");
279                         ParameterInfo[] p = GetParameters ();
280                         for (int i = 0; i < p.Length; ++i) {
281                                 if (i > 0)
282                                         sb.Append (", ");
283                                 Type pt = p[i].ParameterType;
284                                 bool byref = pt.IsByRef;
285                                 if (byref)
286                                         pt = pt.GetElementType ();
287                                 if (pt.IsClass)
288                                         sb.Append (pt.ToString ());
289                                 else
290                                         sb.Append (pt.Name);
291                                 if (byref)
292                                         sb.Append (" ByRef");
293                         }
294                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
295                                 if (p.Length > 0)
296                                         sb.Append (", ");
297                                 sb.Append ("...");
298                         }
299                         
300                         sb.Append (")");
301                         return sb.ToString ();
302                 }
303
304         
305                 // ISerializable
306                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
307                 {
308 #if NET_2_0
309                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
310                                 ? GetGenericArguments () : null;
311                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
312 #else
313                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
314 #endif
315                 }
316
317 #if NET_2_0 || BOOTSTRAP_NET_2_0
318                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
319                 {
320                         if (methodInstantiation == null)
321                                 throw new ArgumentNullException ("methodInstantiation");
322                         foreach (Type type in methodInstantiation)
323                                 if (type == null)
324                                         throw new ArgumentNullException ();
325
326                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
327                         if (ret == null)
328                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
329                         return ret;
330                 }
331
332                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
333                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
334
335                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
336                 public override extern Type [] GetGenericArguments ();
337
338                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
339                 extern MethodInfo GetGenericMethodDefinition_impl ();
340
341                 public override MethodInfo GetGenericMethodDefinition ()
342                 {
343                         MethodInfo res = GetGenericMethodDefinition_impl ();
344                         if (res == null)
345                                 throw new InvalidOperationException ();
346
347                         return res;
348                 }
349
350                 public override extern bool IsGenericMethodDefinition {
351                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
352                         get;
353                 }
354
355                 public override extern bool IsGenericMethod {
356                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
357                         get;
358                 }
359
360                 public override bool ContainsGenericParameters {
361                         get {
362                                 if (IsGenericMethod) {
363                                         foreach (Type arg in GetGenericArguments ())
364                                                 if (arg.ContainsGenericParameters)
365                                                         return true;
366                                 }
367                                 return DeclaringType.ContainsGenericParameters;
368                         }
369                 }
370 #endif
371
372 #if NET_2_0
373                 public override MethodBody GetMethodBody () {
374                         return GetMethodBody (mhandle);
375                 }
376 #endif
377         }
378         
379         internal class MonoCMethod : ConstructorInfo, ISerializable
380         {
381                 internal IntPtr mhandle;
382                 string name;
383                 Type reftype;
384                 
385                 public override MethodImplAttributes GetMethodImplementationFlags() {
386                         MonoMethodInfo info;
387                         MonoMethodInfo.get_method_info (mhandle, out info);
388                         return info.iattrs;
389                 }
390
391                 public override ParameterInfo[] GetParameters() {
392                         return MonoMethodInfo.get_parameter_info (mhandle);
393                 }
394
395                 /*
396                  * InternalInvoke() receives the parameters corretcly converted by the binder
397                  * to match the types of the method signature.
398                  */
399                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
400                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
401
402                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
403                 {
404                         if (binder == null)
405                                 binder = Binder.DefaultBinder;
406                         ParameterInfo[] pinfo = GetParameters ();
407                         if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
408                                 throw new ArgumentException ("parameters");
409
410                         if (SecurityManager.SecurityEnabled) {
411                                 // sadly Attributes doesn't tell us which kind of security action this is so
412                                 // we must do it the hard way - and it also means that we can skip calling
413                                 // Attribute (which is another an icall)
414                                 SecurityManager.ReflectedLinkDemandInvoke (this);
415                         }
416
417 #if NET_2_0
418                         if (obj == null && DeclaringType.ContainsGenericParameters)
419                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
420 #endif
421
422                         Exception exc = null;
423                         object o = null;
424
425                         try {
426                                 o = InternalInvoke (obj, parameters, out exc);
427 #if NET_2_1
428                         } catch (MethodAccessException) {
429                                 throw;
430 #endif
431                         } catch (Exception e) {
432                                 throw new TargetInvocationException (e);
433                         }
434
435                         if (exc != null)
436                                 throw exc;
437                         return o;
438                 }
439
440                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
441                         return Invoke (null, invokeAttr, binder, parameters, culture);
442                 }
443
444                 public override RuntimeMethodHandle MethodHandle { 
445                         get {return new RuntimeMethodHandle (mhandle);} 
446                 }
447                 public override MethodAttributes Attributes { 
448                         get {
449                                 MonoMethodInfo info;
450                                 MonoMethodInfo.get_method_info (mhandle, out info);
451                                 return info.attrs;
452                         } 
453                 }
454
455                 public override CallingConventions CallingConvention { 
456                         get {
457                                 MonoMethodInfo info;
458                                 MonoMethodInfo.get_method_info (mhandle, out info);
459                                 return info.callconv;
460                         }
461                 }
462                 
463                 public override Type ReflectedType {
464                         get {
465                                 return reftype;
466                         }
467                 }
468                 public override Type DeclaringType {
469                         get {
470                                 MonoMethodInfo info;
471                                 MonoMethodInfo.get_method_info (mhandle, out info);
472                                 return info.parent;
473                         }
474                 }
475                 public override string Name {
476                         get {
477                                 if (name != null)
478                                         return name;
479                                 return MonoMethod.get_name (this);
480                         }
481                 }
482
483                 public override bool IsDefined (Type attributeType, bool inherit) {
484                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
485                 }
486
487                 public override object[] GetCustomAttributes( bool inherit) {
488                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
489                 }
490
491                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
492                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
493                 }
494
495 #if NET_2_0
496                 public override MethodBody GetMethodBody () {
497                         return GetMethodBody (mhandle);
498                 }
499 #endif
500
501                 public override string ToString () {
502                         StringBuilder sb = new StringBuilder ();
503                         sb.Append ("Void ");
504                         sb.Append (Name);
505                         sb.Append ("(");
506                         ParameterInfo[] p = GetParameters ();
507                         for (int i = 0; i < p.Length; ++i) {
508                                 if (i > 0)
509                                         sb.Append (", ");
510                                 sb.Append (p[i].ParameterType.Name);
511                         }
512                         sb.Append (")");
513                         return sb.ToString ();
514                 }
515
516                 // ISerializable
517                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
518                 {
519                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
520                 }
521         }
522 }