2008-02-02 Rodrigo Kumpera <rkumpera@novell.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 #pragma warning disable 649
69                 internal IntPtr mhandle;
70                 string name;
71                 Type reftype;
72 #pragma warning restore 649
73
74                 internal MonoMethod () {
75                 }
76
77                 internal MonoMethod (RuntimeMethodHandle mhandle) {
78                         this.mhandle = mhandle.Value;
79                 }
80                 
81                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
82                 internal static extern string get_name (MethodBase method);
83
84                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
85                 internal static extern MonoMethod get_base_definition (MonoMethod method);
86
87                 public override MethodInfo GetBaseDefinition ()
88                 {
89                         return get_base_definition (this);
90                 }
91
92 #if NET_2_0 || BOOTSTRAP_NET_2_0
93                 public override ParameterInfo ReturnParameter {
94                         get {
95                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
96                         }
97                 }
98 #endif
99
100                 public override Type ReturnType {
101                         get {
102                                 MonoMethodInfo info;
103                                 MonoMethodInfo.get_method_info (mhandle, out info);
104                                 return info.ret;
105                         }
106                 }
107                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
108                         get {
109                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
110                         }
111                 }
112                 
113                 public override MethodImplAttributes GetMethodImplementationFlags() {
114                         MonoMethodInfo info;
115                         MonoMethodInfo.get_method_info (mhandle, out info);
116                         return info.iattrs;
117                 }
118
119                 public override ParameterInfo[] GetParameters() {
120                         return MonoMethodInfo.get_parameter_info (mhandle);
121                 }
122
123                 /*
124                  * InternalInvoke() receives the parameters correctly converted by the 
125                  * binder to match the types of the method signature.
126                  */
127                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
128                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
129                 
130                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
131                 {
132                         if (binder == null)
133                                 binder = Binder.DefaultBinder;
134                         ParameterInfo[] pinfo = GetParameters ();
135                         if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
136                                 throw new ArgumentException ("parameters");
137
138 #if !NET_2_1
139                         if (SecurityManager.SecurityEnabled) {
140                                 // sadly Attributes doesn't tell us which kind of security action this is so
141                                 // we must do it the hard way - and it also means that we can skip calling
142                                 // Attribute (which is another an icall)
143                                 SecurityManager.ReflectedLinkDemandInvoke (this);
144                         }
145 #endif
146
147 #if NET_2_0
148                         if (ContainsGenericParameters)
149                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
150 #endif
151
152                         Exception exc;
153                         object o = null;
154
155                         try {
156                                 // The ex argument is used to distinguish exceptions thrown by the icall
157                                 // from the exceptions thrown by the called method (which need to be
158                                 // wrapped in TargetInvocationException).
159                                 o = InternalInvoke (obj, parameters, out exc);
160 #if NET_2_0
161                         } catch (ThreadAbortException) {
162                                 throw;
163 #endif
164 #if NET_2_1
165                         } catch (MethodAccessException) {
166                                 throw;
167 #endif
168                         } catch (Exception e) {
169                                 throw new TargetInvocationException (e);
170                         }
171
172                         if (exc != null)
173                                 throw exc;
174                         return o;
175                 }
176
177                 public override RuntimeMethodHandle MethodHandle { 
178                         get {return new RuntimeMethodHandle (mhandle);} 
179                 }
180                 public override MethodAttributes Attributes { 
181                         get {
182                                 MonoMethodInfo info;
183                                 MonoMethodInfo.get_method_info (mhandle, out info);
184                                 return info.attrs;
185                         } 
186                 }
187
188                 public override CallingConventions CallingConvention { 
189                         get {
190                                 MonoMethodInfo info;
191                                 MonoMethodInfo.get_method_info (mhandle, out info);
192                                 return info.callconv;
193                         }
194                 }
195                 
196                 public override Type ReflectedType {
197                         get {
198                                 return reftype;
199                         }
200                 }
201                 public override Type DeclaringType {
202                         get {
203                                 MonoMethodInfo info;
204                                 MonoMethodInfo.get_method_info (mhandle, out info);
205                                 return info.parent;
206                         }
207                 }
208                 public override string Name {
209                         get {
210                                 if (name != null)
211                                         return name;
212                                 return get_name (this);
213                         }
214                 }
215                 
216                 public override bool IsDefined (Type attributeType, bool inherit) {
217                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
218                 }
219
220                 public override object[] GetCustomAttributes( bool inherit) {
221                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
222                 }
223                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
224                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
225                 }
226
227                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
228                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
229
230                 internal object[] GetPseudoCustomAttributes ()
231                 {
232                         int count = 0;
233
234                         /* MS.NET doesn't report MethodImplAttribute */
235
236                         MonoMethodInfo info;
237                         MonoMethodInfo.get_method_info (mhandle, out info);
238                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
239                                 count ++;
240                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
241                                 count ++;
242                         
243                         if (count == 0)
244                                 return null;
245                         object[] attrs = new object [count];
246                         count = 0;
247
248                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
249                                 attrs [count ++] = new PreserveSigAttribute ();
250                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
251                                 DllImportAttribute attr = GetDllImportAttribute (mhandle);
252                                 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
253                                         attr.PreserveSig = true;
254                                 attrs [count ++] = attr;
255                         }
256
257                         return attrs;
258                 }
259
260                 static bool ShouldPrintFullName (Type type) {
261                         return type.IsClass && (!type.IsPointer || (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
262                 }
263                 public override string ToString () {
264                         StringBuilder sb = new StringBuilder ();
265                         Type retType = ReturnType;
266                         if (ShouldPrintFullName (retType))
267                                 sb.Append (retType.ToString ());
268                         else
269                                 sb.Append (retType.Name);
270                         sb.Append (" ");
271                         sb.Append (Name);
272 #if NET_2_0 || BOOTSTRAP_NET_2_0
273                         if (IsGenericMethod) {
274                                 Type[] gen_params = GetGenericArguments ();
275                                 sb.Append ("[");
276                                 for (int j = 0; j < gen_params.Length; j++) {
277                                         if (j > 0)
278                                                 sb.Append (",");
279                                         sb.Append (gen_params [j].Name);
280                                 }
281                                 sb.Append ("]");
282                         }
283 #endif
284                         sb.Append ("(");
285                         ParameterInfo[] p = GetParameters ();
286                         for (int i = 0; i < p.Length; ++i) {
287                                 if (i > 0)
288                                         sb.Append (", ");
289                                 Type pt = p[i].ParameterType;
290                                 bool byref = pt.IsByRef;
291                                 if (byref)
292                                         pt = pt.GetElementType ();
293                                 if (ShouldPrintFullName (pt))
294                                         sb.Append (pt.ToString ());
295                                 else
296                                         sb.Append (pt.Name);
297                                 if (byref)
298                                         sb.Append (" ByRef");
299                         }
300                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
301                                 if (p.Length > 0)
302                                         sb.Append (", ");
303                                 sb.Append ("...");
304                         }
305                         
306                         sb.Append (")");
307                         return sb.ToString ();
308                 }
309
310         
311                 // ISerializable
312                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
313                 {
314 #if NET_2_0
315                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
316                                 ? GetGenericArguments () : null;
317                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
318 #else
319                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
320 #endif
321                 }
322
323 #if NET_2_0 || BOOTSTRAP_NET_2_0
324                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
325                 {
326                         if (methodInstantiation == null)
327                                 throw new ArgumentNullException ("methodInstantiation");
328                         foreach (Type type in methodInstantiation)
329                                 if (type == null)
330                                         throw new ArgumentNullException ();
331
332                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
333                         if (ret == null)
334                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
335                         return ret;
336                 }
337
338                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
339                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
340
341                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
342                 public override extern Type [] GetGenericArguments ();
343
344                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
345                 extern MethodInfo GetGenericMethodDefinition_impl ();
346
347                 public override MethodInfo GetGenericMethodDefinition ()
348                 {
349                         MethodInfo res = GetGenericMethodDefinition_impl ();
350                         if (res == null)
351                                 throw new InvalidOperationException ();
352
353                         return res;
354                 }
355
356                 public override extern bool IsGenericMethodDefinition {
357                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
358                         get;
359                 }
360
361                 public override extern bool IsGenericMethod {
362                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
363                         get;
364                 }
365
366                 public override bool ContainsGenericParameters {
367                         get {
368                                 if (IsGenericMethod) {
369                                         foreach (Type arg in GetGenericArguments ())
370                                                 if (arg.ContainsGenericParameters)
371                                                         return true;
372                                 }
373                                 return DeclaringType.ContainsGenericParameters;
374                         }
375                 }
376 #endif
377
378 #if NET_2_0
379                 public override MethodBody GetMethodBody () {
380                         return GetMethodBody (mhandle);
381                 }
382 #endif
383         }
384         
385         internal class MonoCMethod : ConstructorInfo, ISerializable
386         {
387 #pragma warning disable 649             
388                 internal IntPtr mhandle;
389                 string name;
390                 Type reftype;
391 #pragma warning restore 649             
392                 
393                 public override MethodImplAttributes GetMethodImplementationFlags() {
394                         MonoMethodInfo info;
395                         MonoMethodInfo.get_method_info (mhandle, out info);
396                         return info.iattrs;
397                 }
398
399                 public override ParameterInfo[] GetParameters() {
400                         return MonoMethodInfo.get_parameter_info (mhandle);
401                 }
402
403                 /*
404                  * InternalInvoke() receives the parameters corretcly converted by the binder
405                  * to match the types of the method signature.
406                  */
407                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
409
410                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
411                 {
412                         if (binder == null)
413                                 binder = Binder.DefaultBinder;
414                         ParameterInfo[] pinfo = GetParameters ();
415                         if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
416                                 throw new ArgumentException ("parameters");
417
418                         if (SecurityManager.SecurityEnabled) {
419                                 // sadly Attributes doesn't tell us which kind of security action this is so
420                                 // we must do it the hard way - and it also means that we can skip calling
421                                 // Attribute (which is another an icall)
422                                 SecurityManager.ReflectedLinkDemandInvoke (this);
423                         }
424
425 #if NET_2_0
426                         if (obj == null && DeclaringType.ContainsGenericParameters)
427                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
428 #endif
429
430                         if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
431                                 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
432                         }
433
434                         Exception exc = null;
435                         object o = null;
436
437                         try {
438                                 o = InternalInvoke (obj, parameters, out exc);
439 #if NET_2_1
440                         } catch (MethodAccessException) {
441                                 throw;
442 #endif
443                         } catch (Exception e) {
444                                 throw new TargetInvocationException (e);
445                         }
446
447                         if (exc != null)
448                                 throw exc;
449                         return (obj == null) ? o : null;
450                 }
451
452                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
453                         return Invoke (null, invokeAttr, binder, parameters, culture);
454                 }
455
456                 public override RuntimeMethodHandle MethodHandle { 
457                         get {return new RuntimeMethodHandle (mhandle);} 
458                 }
459                 public override MethodAttributes Attributes { 
460                         get {
461                                 MonoMethodInfo info;
462                                 MonoMethodInfo.get_method_info (mhandle, out info);
463                                 return info.attrs;
464                         } 
465                 }
466
467                 public override CallingConventions CallingConvention { 
468                         get {
469                                 MonoMethodInfo info;
470                                 MonoMethodInfo.get_method_info (mhandle, out info);
471                                 return info.callconv;
472                         }
473                 }
474                 
475                 public override Type ReflectedType {
476                         get {
477                                 return reftype;
478                         }
479                 }
480                 public override Type DeclaringType {
481                         get {
482                                 MonoMethodInfo info;
483                                 MonoMethodInfo.get_method_info (mhandle, out info);
484                                 return info.parent;
485                         }
486                 }
487                 public override string Name {
488                         get {
489                                 if (name != null)
490                                         return name;
491                                 return MonoMethod.get_name (this);
492                         }
493                 }
494
495                 public override bool IsDefined (Type attributeType, bool inherit) {
496                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
497                 }
498
499                 public override object[] GetCustomAttributes( bool inherit) {
500                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
501                 }
502
503                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
504                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
505                 }
506
507 #if NET_2_0
508                 public override MethodBody GetMethodBody () {
509                         return GetMethodBody (mhandle);
510                 }
511 #endif
512
513                 public override string ToString () {
514                         StringBuilder sb = new StringBuilder ();
515                         sb.Append ("Void ");
516                         sb.Append (Name);
517                         sb.Append ("(");
518                         ParameterInfo[] p = GetParameters ();
519                         for (int i = 0; i < p.Length; ++i) {
520                                 if (i > 0)
521                                         sb.Append (", ");
522                                 sb.Append (p[i].ParameterType.Name);
523                         }
524                         sb.Append (")");
525                         return sb.ToString ();
526                 }
527
528                 // ISerializable
529                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
530                 {
531                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
532                 }
533         }
534 }