2008-11-17 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                 public override string ToString () {
261                         StringBuilder sb = new StringBuilder ();
262                         if (ReturnType.IsClass)
263                                 sb.Append (ReturnType.ToString ());
264                         else
265                                 sb.Append (ReturnType.Name);
266                         sb.Append (" ");
267                         sb.Append (Name);
268 #if NET_2_0 || BOOTSTRAP_NET_2_0
269                         if (IsGenericMethod) {
270                                 Type[] gen_params = GetGenericArguments ();
271                                 sb.Append ("[");
272                                 for (int j = 0; j < gen_params.Length; j++) {
273                                         if (j > 0)
274                                                 sb.Append (",");
275                                         sb.Append (gen_params [j].Name);
276                                 }
277                                 sb.Append ("]");
278                         }
279 #endif
280                         sb.Append ("(");
281                         ParameterInfo[] p = GetParameters ();
282                         for (int i = 0; i < p.Length; ++i) {
283                                 if (i > 0)
284                                         sb.Append (", ");
285                                 Type pt = p[i].ParameterType;
286                                 bool byref = pt.IsByRef;
287                                 if (byref)
288                                         pt = pt.GetElementType ();
289                                 if (pt.IsClass)
290                                         sb.Append (pt.ToString ());
291                                 else
292                                         sb.Append (pt.Name);
293                                 if (byref)
294                                         sb.Append (" ByRef");
295                         }
296                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
297                                 if (p.Length > 0)
298                                         sb.Append (", ");
299                                 sb.Append ("...");
300                         }
301                         
302                         sb.Append (")");
303                         return sb.ToString ();
304                 }
305
306         
307                 // ISerializable
308                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
309                 {
310 #if NET_2_0
311                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
312                                 ? GetGenericArguments () : null;
313                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
314 #else
315                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
316 #endif
317                 }
318
319 #if NET_2_0 || BOOTSTRAP_NET_2_0
320                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
321                 {
322                         if (methodInstantiation == null)
323                                 throw new ArgumentNullException ("methodInstantiation");
324                         foreach (Type type in methodInstantiation)
325                                 if (type == null)
326                                         throw new ArgumentNullException ();
327
328                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
329                         if (ret == null)
330                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
331                         return ret;
332                 }
333
334                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
335                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
336
337                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
338                 public override extern Type [] GetGenericArguments ();
339
340                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
341                 extern MethodInfo GetGenericMethodDefinition_impl ();
342
343                 public override MethodInfo GetGenericMethodDefinition ()
344                 {
345                         MethodInfo res = GetGenericMethodDefinition_impl ();
346                         if (res == null)
347                                 throw new InvalidOperationException ();
348
349                         return res;
350                 }
351
352                 public override extern bool IsGenericMethodDefinition {
353                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
354                         get;
355                 }
356
357                 public override extern bool IsGenericMethod {
358                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
359                         get;
360                 }
361
362                 public override bool ContainsGenericParameters {
363                         get {
364                                 if (IsGenericMethod) {
365                                         foreach (Type arg in GetGenericArguments ())
366                                                 if (arg.ContainsGenericParameters)
367                                                         return true;
368                                 }
369                                 return DeclaringType.ContainsGenericParameters;
370                         }
371                 }
372 #endif
373
374 #if NET_2_0
375                 public override MethodBody GetMethodBody () {
376                         return GetMethodBody (mhandle);
377                 }
378 #endif
379         }
380         
381         internal class MonoCMethod : ConstructorInfo, ISerializable
382         {
383 #pragma warning disable 649             
384                 internal IntPtr mhandle;
385                 string name;
386                 Type reftype;
387 #pragma warning restore 649             
388                 
389                 public override MethodImplAttributes GetMethodImplementationFlags() {
390                         MonoMethodInfo info;
391                         MonoMethodInfo.get_method_info (mhandle, out info);
392                         return info.iattrs;
393                 }
394
395                 public override ParameterInfo[] GetParameters() {
396                         return MonoMethodInfo.get_parameter_info (mhandle);
397                 }
398
399                 /*
400                  * InternalInvoke() receives the parameters corretcly converted by the binder
401                  * to match the types of the method signature.
402                  */
403                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
404                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
405
406                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
407                 {
408                         if (binder == null)
409                                 binder = Binder.DefaultBinder;
410                         ParameterInfo[] pinfo = GetParameters ();
411                         if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
412                                 throw new ArgumentException ("parameters");
413
414                         if (SecurityManager.SecurityEnabled) {
415                                 // sadly Attributes doesn't tell us which kind of security action this is so
416                                 // we must do it the hard way - and it also means that we can skip calling
417                                 // Attribute (which is another an icall)
418                                 SecurityManager.ReflectedLinkDemandInvoke (this);
419                         }
420
421 #if NET_2_0
422                         if (obj == null && DeclaringType.ContainsGenericParameters)
423                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
424 #endif
425
426                         if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
427                                 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
428                         }
429
430                         Exception exc = null;
431                         object o = null;
432
433                         try {
434                                 o = InternalInvoke (obj, parameters, out exc);
435 #if NET_2_1
436                         } catch (MethodAccessException) {
437                                 throw;
438 #endif
439                         } catch (Exception e) {
440                                 throw new TargetInvocationException (e);
441                         }
442
443                         if (exc != null)
444                                 throw exc;
445                         return (obj == null) ? o : null;
446                 }
447
448                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
449                         return Invoke (null, invokeAttr, binder, parameters, culture);
450                 }
451
452                 public override RuntimeMethodHandle MethodHandle { 
453                         get {return new RuntimeMethodHandle (mhandle);} 
454                 }
455                 public override MethodAttributes Attributes { 
456                         get {
457                                 MonoMethodInfo info;
458                                 MonoMethodInfo.get_method_info (mhandle, out info);
459                                 return info.attrs;
460                         } 
461                 }
462
463                 public override CallingConventions CallingConvention { 
464                         get {
465                                 MonoMethodInfo info;
466                                 MonoMethodInfo.get_method_info (mhandle, out info);
467                                 return info.callconv;
468                         }
469                 }
470                 
471                 public override Type ReflectedType {
472                         get {
473                                 return reftype;
474                         }
475                 }
476                 public override Type DeclaringType {
477                         get {
478                                 MonoMethodInfo info;
479                                 MonoMethodInfo.get_method_info (mhandle, out info);
480                                 return info.parent;
481                         }
482                 }
483                 public override string Name {
484                         get {
485                                 if (name != null)
486                                         return name;
487                                 return MonoMethod.get_name (this);
488                         }
489                 }
490
491                 public override bool IsDefined (Type attributeType, bool inherit) {
492                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
493                 }
494
495                 public override object[] GetCustomAttributes( bool inherit) {
496                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
497                 }
498
499                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
500                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
501                 }
502
503 #if NET_2_0
504                 public override MethodBody GetMethodBody () {
505                         return GetMethodBody (mhandle);
506                 }
507 #endif
508
509                 public override string ToString () {
510                         StringBuilder sb = new StringBuilder ();
511                         sb.Append ("Void ");
512                         sb.Append (Name);
513                         sb.Append ("(");
514                         ParameterInfo[] p = GetParameters ();
515                         for (int i = 0; i < p.Length; ++i) {
516                                 if (i > 0)
517                                         sb.Append (", ");
518                                 sb.Append (p[i].ParameterType.Name);
519                         }
520                         sb.Append (")");
521                         return sb.ToString ();
522                 }
523
524                 // ISerializable
525                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
526                 {
527                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
528                 }
529         }
530 }