[runtime] Updates comments.
[mono.git] / mcs / class / corlib / System.Reflection / MonoMethod.cs
1 //
2 // MonoMethod.cs: The class used to represent methods from the mono runtime.
3 //
4 // Authors:
5 //   Paolo Molaro (lupus@ximian.com)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 // Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections.Generic;
33 using System.Globalization;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Runtime.Serialization;
37 #if !FULL_AOT_RUNTIME
38 using System.Reflection.Emit;
39 #endif
40 using System.Security;
41 using System.Threading;
42 using System.Text;
43 using System.Diagnostics;
44
45 namespace System.Reflection {
46         
47         internal struct MonoMethodInfo 
48         {
49 #pragma warning disable 649     
50                 private Type parent;
51                 private Type ret;
52                 internal MethodAttributes attrs;
53                 internal MethodImplAttributes iattrs;
54                 private CallingConventions callconv;
55 #pragma warning restore 649             
56
57                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58                 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
59                 
60                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
61                 static extern int get_method_attributes (IntPtr handle);
62                 
63                 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
64                 {
65                         MonoMethodInfo info;
66                         MonoMethodInfo.get_method_info (handle, out info);
67                         return info;
68                 }
69
70                 internal static Type GetDeclaringType (IntPtr handle)
71                 {
72                         return GetMethodInfo (handle).parent;
73                 }
74
75                 internal static Type GetReturnType (IntPtr handle)
76                 {
77                         return GetMethodInfo (handle).ret;
78                 }
79
80                 internal static MethodAttributes GetAttributes (IntPtr handle)
81                 {
82                         return (MethodAttributes)get_method_attributes (handle);
83                 }
84
85                 internal static CallingConventions GetCallingConvention (IntPtr handle)
86                 {
87                         return GetMethodInfo (handle).callconv;
88                 }
89
90                 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
91                 {
92                         return GetMethodInfo (handle).iattrs;
93                 }
94
95                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
96                 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
97
98                 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
99                 {
100                         return get_parameter_info (handle, member);
101                 }
102
103                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
104                 static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
105
106                 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
107                 {
108                         return ParameterInfo.New (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
109                 }
110         };
111         
112         abstract class RuntimeMethodInfo : MethodInfo
113         {
114                 internal BindingFlags BindingFlags {
115                         get {
116                                 return 0;
117                         }
118                 }
119         }
120
121         /*
122          * Note: most of this class needs to be duplicated for the contructor, since
123          * the .NET reflection class hierarchy is so broken.
124          */
125         [Serializable()]
126         [StructLayout (LayoutKind.Sequential)]
127         internal class MonoMethod : RuntimeMethodInfo, ISerializable
128         {
129 #pragma warning disable 649
130                 internal IntPtr mhandle;
131                 string name;
132                 Type reftype;
133 #pragma warning restore 649
134
135                 internal MonoMethod () {
136                 }
137
138                 internal MonoMethod (RuntimeMethodHandle mhandle) {
139                         this.mhandle = mhandle.Value;
140                 }
141                 
142                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
143                 internal static extern string get_name (MethodBase method);
144
145                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
146                 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
147
148                 public override MethodInfo GetBaseDefinition ()
149                 {
150                         return get_base_method (this, true);
151                 }
152
153                 internal override MethodInfo GetBaseMethod ()
154                 {
155                         return get_base_method (this, false);
156                 }
157
158                 public override ParameterInfo ReturnParameter {
159                         get {
160                                 return MonoMethodInfo.GetReturnParameterInfo (this);
161                         }
162                 }
163
164                 public override Type ReturnType {
165                         get {
166                                 return MonoMethodInfo.GetReturnType (mhandle);
167                         }
168                 }
169                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
170                         get {
171                                 return MonoMethodInfo.GetReturnParameterInfo (this);
172                         }
173                 }
174                 
175                 public override MethodImplAttributes GetMethodImplementationFlags ()
176                 {
177                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
178                 }
179
180                 public override ParameterInfo[] GetParameters ()
181                 {
182                         var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
183                         if (src.Length == 0)
184                                 return src;
185
186                         // Have to clone because GetParametersInfo icall returns cached value
187                         var dest = new ParameterInfo [src.Length];
188                         Array.FastCopy (src, 0, dest, 0, src.Length);
189                         return dest;
190                 }
191
192                 internal override ParameterInfo[] GetParametersInternal ()
193                 {
194                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
195                 }
196                 
197                 internal override int GetParametersCount ()
198                 {
199                         return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
200                 }
201
202                 /*
203                  * InternalInvoke() receives the parameters correctly converted by the 
204                  * binder to match the types of the method signature.
205                  */
206                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
207                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
208
209                 [DebuggerHidden]
210                 [DebuggerStepThrough]
211                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
212                 {
213                         if (binder == null)
214                                 binder = Type.DefaultBinder;
215
216                         /*Avoid allocating an array every time*/
217                         ParameterInfo[] pinfo = GetParametersInternal ();
218                         ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
219
220 #if !NET_2_1
221                         if (SecurityManager.SecurityEnabled) {
222                                 // sadly Attributes doesn't tell us which kind of security action this is so
223                                 // we must do it the hard way - and it also means that we can skip calling
224                                 // Attribute (which is another an icall)
225                                 SecurityManager.ReflectedLinkDemandInvoke (this);
226                         }
227 #endif
228
229                         if (ContainsGenericParameters)
230                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
231
232                         Exception exc;
233                         object o = null;
234
235                         try {
236                                 // The ex argument is used to distinguish exceptions thrown by the icall
237                                 // from the exceptions thrown by the called method (which need to be
238                                 // wrapped in TargetInvocationException).
239                                 o = InternalInvoke (obj, parameters, out exc);
240                         } catch (ThreadAbortException) {
241                                 throw;
242 #if NET_2_1
243                         } catch (MethodAccessException) {
244                                 throw;
245 #endif
246                         } catch (Exception e) {
247                                 throw new TargetInvocationException (e);
248                         }
249
250                         if (exc != null)
251                                 throw exc;
252                         return o;
253                 }
254
255                 internal static void ConvertValues (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture, BindingFlags invokeAttr)
256                 {
257                         if (args == null) {
258                                 if (pinfo.Length == 0)
259                                         return;
260
261                                 throw new TargetParameterCountException ();
262                         }
263
264                         if (pinfo.Length != args.Length)
265                                 throw new TargetParameterCountException ();
266
267                         for (int i = 0; i < args.Length; ++i) {
268                                 var arg = args [i];
269                                 var pi = pinfo [i];
270                                 if (arg == Type.Missing) {
271                                         if (pi.DefaultValue == System.DBNull.Value)
272                                                 throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters");
273
274                                         args [i] = pi.DefaultValue;
275                                         continue;
276                                 }
277
278                                 var rt = (RuntimeType) pi.ParameterType;
279                                 args [i] = rt.CheckValue (arg, binder, culture, invokeAttr);
280                         }
281                 }
282
283                 public override RuntimeMethodHandle MethodHandle { 
284                         get {
285                                 return new RuntimeMethodHandle (mhandle);
286                         } 
287                 }
288                 
289                 public override MethodAttributes Attributes { 
290                         get {
291                                 return MonoMethodInfo.GetAttributes (mhandle);
292                         } 
293                 }
294
295                 public override CallingConventions CallingConvention { 
296                         get {
297                                 return MonoMethodInfo.GetCallingConvention (mhandle);
298                         }
299                 }
300                 
301                 public override Type ReflectedType {
302                         get {
303                                 return reftype;
304                         }
305                 }
306                 public override Type DeclaringType {
307                         get {
308                                 return MonoMethodInfo.GetDeclaringType (mhandle);
309                         }
310                 }
311                 public override string Name {
312                         get {
313                                 if (name != null)
314                                         return name;
315                                 return get_name (this);
316                         }
317                 }
318                 
319                 public override bool IsDefined (Type attributeType, bool inherit) {
320                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
321                 }
322
323                 public override object[] GetCustomAttributes( bool inherit) {
324                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
325                 }
326                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
327                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
328                 }
329
330                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
331                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
332
333                 internal object[] GetPseudoCustomAttributes ()
334                 {
335                         int count = 0;
336
337                         /* MS.NET doesn't report MethodImplAttribute */
338
339                         MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
340                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
341                                 count ++;
342                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
343                                 count ++;
344                         
345                         if (count == 0)
346                                 return null;
347                         object[] attrs = new object [count];
348                         count = 0;
349
350                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
351                                 attrs [count ++] = new PreserveSigAttribute ();
352                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
353                                 DllImportAttribute attr = GetDllImportAttribute (mhandle);
354                                 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
355                                         attr.PreserveSig = true;
356                                 attrs [count ++] = attr;
357                         }
358
359                         return attrs;
360                 }
361
362                 public override string ToString () {
363                         StringBuilder sb = new StringBuilder ();
364                         Type retType = ReturnType;
365                         if (Type.ShouldPrintFullName (retType))
366                                 sb.Append (retType.ToString ());
367                         else
368                                 sb.Append (retType.Name);
369                         sb.Append (" ");
370                         sb.Append (Name);
371                         if (IsGenericMethod) {
372                                 Type[] gen_params = GetGenericArguments ();
373                                 sb.Append ("[");
374                                 for (int j = 0; j < gen_params.Length; j++) {
375                                         if (j > 0)
376                                                 sb.Append (",");
377                                         sb.Append (gen_params [j].Name);
378                                 }
379                                 sb.Append ("]");
380                         }
381                         sb.Append ("(");
382
383                         var p = GetParametersInternal ();
384                         ParameterInfo.FormatParameters (sb, p);
385
386                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
387                                 if (p.Length > 0)
388                                         sb.Append (", ");
389                                 sb.Append ("...");
390                         }
391                         
392                         sb.Append (")");
393                         return sb.ToString ();
394                 }
395
396         
397                 // ISerializable
398                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
399                 {
400                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
401                                 ? GetGenericArguments () : null;
402                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
403                 }
404
405                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
406                 {
407                         if (methodInstantiation == null)
408                                 throw new ArgumentNullException ("methodInstantiation");
409
410                         if (!IsGenericMethodDefinition)
411                                 throw new InvalidOperationException ("not a generic method definition");
412
413                         /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
414                         if (GetGenericArguments ().Length != methodInstantiation.Length)
415                                 throw new ArgumentException ("Incorrect length");
416
417                         bool hasUserType = false;
418                         foreach (Type type in methodInstantiation) {
419                                 if (type == null)
420                                         throw new ArgumentNullException ();
421                                 if (!(type is MonoType))
422                                         hasUserType = true;
423                         }
424
425                         if (hasUserType)
426 #if FULL_AOT_RUNTIME
427                                 throw new NotSupportedException ("User types are not supported under full aot");
428 #else
429                                 return new MethodOnTypeBuilderInst (this, methodInstantiation);
430 #endif
431
432                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
433                         if (ret == null)
434                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
435                         return ret;
436                 }
437
438                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
439                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
440
441                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
442                 public override extern Type [] GetGenericArguments ();
443
444                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
445                 extern MethodInfo GetGenericMethodDefinition_impl ();
446
447                 public override MethodInfo GetGenericMethodDefinition ()
448                 {
449                         MethodInfo res = GetGenericMethodDefinition_impl ();
450                         if (res == null)
451                                 throw new InvalidOperationException ();
452
453                         return res;
454                 }
455
456                 public override extern bool IsGenericMethodDefinition {
457                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
458                         get;
459                 }
460
461                 public override extern bool IsGenericMethod {
462                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
463                         get;
464                 }
465
466                 public override bool ContainsGenericParameters {
467                         get {
468                                 if (IsGenericMethod) {
469                                         foreach (Type arg in GetGenericArguments ())
470                                                 if (arg.ContainsGenericParameters)
471                                                         return true;
472                                 }
473                                 return DeclaringType.ContainsGenericParameters;
474                         }
475                 }
476
477                 public override MethodBody GetMethodBody () {
478                         return GetMethodBody (mhandle);
479                 }
480
481                 public override IList<CustomAttributeData> GetCustomAttributesData () {
482                         return CustomAttributeData.GetCustomAttributes (this);
483                 }
484         }
485         
486
487         abstract class RuntimeConstructorInfo : ConstructorInfo
488         {
489                 internal BindingFlags BindingFlags {
490                         get {
491                                 return 0;
492                         }
493                 }
494         }
495
496         [Serializable()]
497         [StructLayout (LayoutKind.Sequential)]
498         internal class MonoCMethod : RuntimeConstructorInfo, ISerializable
499         {
500 #pragma warning disable 649             
501                 internal IntPtr mhandle;
502                 string name;
503                 Type reftype;
504 #pragma warning restore 649             
505                 
506                 public override MethodImplAttributes GetMethodImplementationFlags ()
507                 {
508                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
509                 }
510
511                 public override ParameterInfo[] GetParameters ()
512                 {
513                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
514                 }
515
516                 internal override ParameterInfo[] GetParametersInternal ()
517                 {
518                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
519                 }               
520
521                 internal override int GetParametersCount ()
522                 {
523                         var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
524                         return pi == null ? 0 : pi.Length;
525                 }
526
527                 /*
528                  * InternalInvoke() receives the parameters correctly converted by the binder
529                  * to match the types of the method signature.
530                  */
531                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
532                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
533
534                 [DebuggerHidden]
535                 [DebuggerStepThrough]
536                 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
537                 {
538                         if (obj == null) {
539                                 if (!IsStatic)
540                                         throw new TargetException ("Instance constructor requires a target");
541                         } else if (!DeclaringType.IsInstanceOfType (obj)) {
542                                 throw new TargetException ("Constructor does not match target type");                           
543                         }
544
545                         return DoInvoke (obj, invokeAttr, binder, parameters, culture);
546                 }
547
548                 object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
549                 {
550                         if (binder == null)
551                                 binder = Type.DefaultBinder;
552
553                         ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
554
555                         MonoMethod.ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
556
557 #if !NET_2_1
558                         if (SecurityManager.SecurityEnabled) {
559                                 // sadly Attributes doesn't tell us which kind of security action this is so
560                                 // we must do it the hard way - and it also means that we can skip calling
561                                 // Attribute (which is another an icall)
562                                 SecurityManager.ReflectedLinkDemandInvoke (this);
563                         }
564 #endif
565
566                         if (obj == null && DeclaringType.ContainsGenericParameters)
567                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
568
569                         if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
570                                 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
571                         }
572
573                         return InternalInvoke (obj, parameters);
574                 }
575
576                 public object InternalInvoke (object obj, object[] parameters)
577                 {
578                         Exception exc;
579                         object o = null;
580
581                         try {
582                                 o = InternalInvoke (obj, parameters, out exc);
583 #if NET_2_1
584                         } catch (MethodAccessException) {
585                                 throw;
586 #endif
587                         } catch (Exception e) {
588                                 throw new TargetInvocationException (e);
589                         }
590
591                         if (exc != null)
592                                 throw exc;
593
594                         return obj == null ? o : null;
595                 }
596
597                 [DebuggerHidden]
598                 [DebuggerStepThrough]
599                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
600                 {
601                         return DoInvoke (null, invokeAttr, binder, parameters, culture);
602                 }
603
604                 public override RuntimeMethodHandle MethodHandle { 
605                         get {
606                                 return new RuntimeMethodHandle (mhandle);
607                         } 
608                 }
609                 
610                 public override MethodAttributes Attributes { 
611                         get {
612                                 return MonoMethodInfo.GetAttributes (mhandle);
613                         } 
614                 }
615
616                 public override CallingConventions CallingConvention { 
617                         get {
618                                 return MonoMethodInfo.GetCallingConvention (mhandle);
619                         }
620                 }
621                 
622                 public override bool ContainsGenericParameters {
623                         get {
624                                 return DeclaringType.ContainsGenericParameters;
625                         }
626                 }
627
628                 public override Type ReflectedType {
629                         get {
630                                 return reftype;
631                         }
632                 }
633                 public override Type DeclaringType {
634                         get {
635                                 return MonoMethodInfo.GetDeclaringType (mhandle);
636                         }
637                 }
638                 public override string Name {
639                         get {
640                                 if (name != null)
641                                         return name;
642                                 return MonoMethod.get_name (this);
643                         }
644                 }
645
646                 public override bool IsDefined (Type attributeType, bool inherit) {
647                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
648                 }
649
650                 public override object[] GetCustomAttributes( bool inherit) {
651                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
652                 }
653
654                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
655                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
656                 }
657
658                 public override MethodBody GetMethodBody () {
659                         return GetMethodBody (mhandle);
660                 }
661
662                 public override string ToString () {
663                         StringBuilder sb = new StringBuilder ();
664                         sb.Append ("Void ");
665                         sb.Append (Name);
666                         sb.Append ("(");
667                         ParameterInfo[] p = GetParameters ();
668                         for (int i = 0; i < p.Length; ++i) {
669                                 if (i > 0)
670                                         sb.Append (", ");
671                                 sb.Append (p[i].ParameterType.Name);
672                         }
673                         if (CallingConvention == CallingConventions.Any)
674                                 sb.Append (", ...");
675                         sb.Append (")");
676                         return sb.ToString ();
677                 }
678
679                 // ISerializable
680                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
681                 {
682                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
683                 }
684
685                 public override IList<CustomAttributeData> GetCustomAttributesData () {
686                         return CustomAttributeData.GetCustomAttributes (this);
687                 }
688         }
689 }