xbuild: use the AdditionalReferencePath items to locate assemblies
[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 new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
109                 }
110         };
111         
112         /*
113          * Note: most of this class needs to be duplicated for the contructor, since
114          * the .NET reflection class hierarchy is so broken.
115          */
116         [Serializable()]
117         [StructLayout (LayoutKind.Sequential)]
118         internal class MonoMethod : MethodInfo, ISerializable
119         {
120 #pragma warning disable 649
121                 internal IntPtr mhandle;
122                 string name;
123                 Type reftype;
124 #pragma warning restore 649
125
126                 internal MonoMethod () {
127                 }
128
129                 internal MonoMethod (RuntimeMethodHandle mhandle) {
130                         this.mhandle = mhandle.Value;
131                 }
132                 
133                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
134                 internal static extern string get_name (MethodBase method);
135
136                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
137                 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
138
139                 public override MethodInfo GetBaseDefinition ()
140                 {
141                         return get_base_method (this, true);
142                 }
143
144                 internal override MethodInfo GetBaseMethod ()
145                 {
146                         return get_base_method (this, false);
147                 }
148
149                 public override ParameterInfo ReturnParameter {
150                         get {
151                                 return MonoMethodInfo.GetReturnParameterInfo (this);
152                         }
153                 }
154
155                 public override Type ReturnType {
156                         get {
157                                 return MonoMethodInfo.GetReturnType (mhandle);
158                         }
159                 }
160                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
161                         get {
162                                 return MonoMethodInfo.GetReturnParameterInfo (this);
163                         }
164                 }
165                 
166                 public override MethodImplAttributes GetMethodImplementationFlags ()
167                 {
168                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
169                 }
170
171                 public override ParameterInfo[] GetParameters ()
172                 {
173                         var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
174                         if (src.Length == 0)
175                                 return src;
176
177                         // Have to clone because GetParametersInfo icall returns cached value
178                         var dest = new ParameterInfo [src.Length];
179                         Array.FastCopy (src, 0, dest, 0, src.Length);
180                         return dest;
181                 }
182
183                 internal override ParameterInfo[] GetParametersInternal ()
184                 {
185                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
186                 }
187                 
188                 internal override int GetParametersCount ()
189                 {
190                         return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
191                 }
192
193                 /*
194                  * InternalInvoke() receives the parameters correctly converted by the 
195                  * binder to match the types of the method signature.
196                  */
197                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
198                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
199
200                 [DebuggerHidden]
201                 [DebuggerStepThrough]
202                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
203                 {
204                         if (binder == null)
205                                 binder = Binder.DefaultBinder;
206
207                         /*Avoid allocating an array every time*/
208                         ParameterInfo[] pinfo = GetParametersInternal ();
209                         binder.ConvertValues (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0);
210
211 #if !NET_2_1
212                         if (SecurityManager.SecurityEnabled) {
213                                 // sadly Attributes doesn't tell us which kind of security action this is so
214                                 // we must do it the hard way - and it also means that we can skip calling
215                                 // Attribute (which is another an icall)
216                                 SecurityManager.ReflectedLinkDemandInvoke (this);
217                         }
218 #endif
219
220                         if (ContainsGenericParameters)
221                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
222
223                         Exception exc;
224                         object o = null;
225
226                         try {
227                                 // The ex argument is used to distinguish exceptions thrown by the icall
228                                 // from the exceptions thrown by the called method (which need to be
229                                 // wrapped in TargetInvocationException).
230                                 o = InternalInvoke (obj, parameters, out exc);
231                         } catch (ThreadAbortException) {
232                                 throw;
233 #if NET_2_1
234                         } catch (MethodAccessException) {
235                                 throw;
236 #endif
237                         } catch (Exception e) {
238                                 throw new TargetInvocationException (e);
239                         }
240
241                         if (exc != null)
242                                 throw exc;
243                         return o;
244                 }
245
246                 public override RuntimeMethodHandle MethodHandle { 
247                         get {
248                                 return new RuntimeMethodHandle (mhandle);
249                         } 
250                 }
251                 
252                 public override MethodAttributes Attributes { 
253                         get {
254                                 return MonoMethodInfo.GetAttributes (mhandle);
255                         } 
256                 }
257
258                 public override CallingConventions CallingConvention { 
259                         get {
260                                 return MonoMethodInfo.GetCallingConvention (mhandle);
261                         }
262                 }
263                 
264                 public override Type ReflectedType {
265                         get {
266                                 return reftype;
267                         }
268                 }
269                 public override Type DeclaringType {
270                         get {
271                                 return MonoMethodInfo.GetDeclaringType (mhandle);
272                         }
273                 }
274                 public override string Name {
275                         get {
276                                 if (name != null)
277                                         return name;
278                                 return get_name (this);
279                         }
280                 }
281                 
282                 public override bool IsDefined (Type attributeType, bool inherit) {
283                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
284                 }
285
286                 public override object[] GetCustomAttributes( bool inherit) {
287                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
288                 }
289                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
290                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
291                 }
292
293                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
294                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
295
296                 internal object[] GetPseudoCustomAttributes ()
297                 {
298                         int count = 0;
299
300                         /* MS.NET doesn't report MethodImplAttribute */
301
302                         MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
303                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
304                                 count ++;
305                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
306                                 count ++;
307                         
308                         if (count == 0)
309                                 return null;
310                         object[] attrs = new object [count];
311                         count = 0;
312
313                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
314                                 attrs [count ++] = new PreserveSigAttribute ();
315                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
316                                 DllImportAttribute attr = GetDllImportAttribute (mhandle);
317                                 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
318                                         attr.PreserveSig = true;
319                                 attrs [count ++] = attr;
320                         }
321
322                         return attrs;
323                 }
324
325                 static bool ShouldPrintFullName (Type type) {
326                         return type.IsClass && (!type.IsPointer ||
327                                 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
328                 }
329
330                 public override string ToString () {
331                         StringBuilder sb = new StringBuilder ();
332                         Type retType = ReturnType;
333                         if (ShouldPrintFullName (retType))
334                                 sb.Append (retType.ToString ());
335                         else
336                                 sb.Append (retType.Name);
337                         sb.Append (" ");
338                         sb.Append (Name);
339                         if (IsGenericMethod) {
340                                 Type[] gen_params = GetGenericArguments ();
341                                 sb.Append ("[");
342                                 for (int j = 0; j < gen_params.Length; j++) {
343                                         if (j > 0)
344                                                 sb.Append (",");
345                                         sb.Append (gen_params [j].Name);
346                                 }
347                                 sb.Append ("]");
348                         }
349                         sb.Append ("(");
350                         ParameterInfo[] p = GetParametersInternal ();
351                         for (int i = 0; i < p.Length; ++i) {
352                                 if (i > 0)
353                                         sb.Append (", ");
354                                 Type pt = p[i].ParameterType;
355                                 bool byref = pt.IsByRef;
356                                 if (byref)
357                                         pt = pt.GetElementType ();
358                                 if (ShouldPrintFullName (pt))
359                                         sb.Append (pt.ToString ());
360                                 else
361                                         sb.Append (pt.Name);
362                                 if (byref)
363                                         sb.Append (" ByRef");
364                         }
365                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
366                                 if (p.Length > 0)
367                                         sb.Append (", ");
368                                 sb.Append ("...");
369                         }
370                         
371                         sb.Append (")");
372                         return sb.ToString ();
373                 }
374
375         
376                 // ISerializable
377                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
378                 {
379                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
380                                 ? GetGenericArguments () : null;
381                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
382                 }
383
384                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
385                 {
386                         if (methodInstantiation == null)
387                                 throw new ArgumentNullException ("methodInstantiation");
388
389                         if (!IsGenericMethodDefinition)
390                                 throw new InvalidOperationException ("not a generic method definition");
391
392                         /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
393                         if (GetGenericArguments ().Length != methodInstantiation.Length)
394                                 throw new ArgumentException ("Incorrect length");
395
396                         bool hasUserType = false;
397                         foreach (Type type in methodInstantiation) {
398                                 if (type == null)
399                                         throw new ArgumentNullException ();
400                                 if (!(type is MonoType))
401                                         hasUserType = true;
402                         }
403
404                         if (hasUserType)
405 #if FULL_AOT_RUNTIME
406                                 throw new NotSupportedException ("User types are not supported under full aot");
407 #else
408                                 return new MethodOnTypeBuilderInst (this, methodInstantiation);
409 #endif
410
411                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
412                         if (ret == null)
413                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
414                         return ret;
415                 }
416
417                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
418                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
419
420                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
421                 public override extern Type [] GetGenericArguments ();
422
423                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
424                 extern MethodInfo GetGenericMethodDefinition_impl ();
425
426                 public override MethodInfo GetGenericMethodDefinition ()
427                 {
428                         MethodInfo res = GetGenericMethodDefinition_impl ();
429                         if (res == null)
430                                 throw new InvalidOperationException ();
431
432                         return res;
433                 }
434
435                 public override extern bool IsGenericMethodDefinition {
436                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
437                         get;
438                 }
439
440                 public override extern bool IsGenericMethod {
441                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
442                         get;
443                 }
444
445                 public override bool ContainsGenericParameters {
446                         get {
447                                 if (IsGenericMethod) {
448                                         foreach (Type arg in GetGenericArguments ())
449                                                 if (arg.ContainsGenericParameters)
450                                                         return true;
451                                 }
452                                 return DeclaringType.ContainsGenericParameters;
453                         }
454                 }
455
456                 public override MethodBody GetMethodBody () {
457                         return GetMethodBody (mhandle);
458                 }
459
460 #if NET_4_0
461                 public override IList<CustomAttributeData> GetCustomAttributesData () {
462                         return CustomAttributeData.GetCustomAttributes (this);
463                 }
464 #endif
465         }
466         
467         [StructLayout (LayoutKind.Sequential)]
468         internal class MonoCMethod : ConstructorInfo, ISerializable
469         {
470 #pragma warning disable 649             
471                 internal IntPtr mhandle;
472                 string name;
473                 Type reftype;
474 #pragma warning restore 649             
475                 
476                 public override MethodImplAttributes GetMethodImplementationFlags ()
477                 {
478                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
479                 }
480
481                 public override ParameterInfo[] GetParameters ()
482                 {
483                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
484                 }
485
486                 internal override ParameterInfo[] GetParametersInternal ()
487                 {
488                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
489                 }               
490
491                 internal override int GetParametersCount ()
492                 {
493                         var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
494                         return pi == null ? 0 : pi.Length;
495                 }
496
497                 /*
498                  * InternalInvoke() receives the parameters correctly converted by the binder
499                  * to match the types of the method signature.
500                  */
501                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
502                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
503
504                 [DebuggerHidden]
505                 [DebuggerStepThrough]
506                 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
507                 {
508                         if (obj == null) {
509                                 if (!IsStatic)
510                                         throw new TargetException ("Instance constructor requires a target");
511                         } else if (!DeclaringType.IsInstanceOfType (obj)) {
512                                 throw new TargetException ("Constructor does not match target type");                           
513                         }
514
515                         return DoInvoke (obj, invokeAttr, binder, parameters, culture);
516                 }
517
518                 object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
519                 {
520                         if (binder == null)
521                                 binder = Binder.DefaultBinder;
522
523                         ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
524
525                         binder.ConvertValues (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0);
526
527 #if !NET_2_1
528                         if (SecurityManager.SecurityEnabled) {
529                                 // sadly Attributes doesn't tell us which kind of security action this is so
530                                 // we must do it the hard way - and it also means that we can skip calling
531                                 // Attribute (which is another an icall)
532                                 SecurityManager.ReflectedLinkDemandInvoke (this);
533                         }
534 #endif
535
536                         if (obj == null && DeclaringType.ContainsGenericParameters)
537                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
538
539                         if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
540                                 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
541                         }
542
543                         return InternalInvoke (obj, parameters);
544                 }
545
546                 public object InternalInvoke (object obj, object[] parameters)
547                 {
548                         Exception exc;
549                         object o = null;
550
551                         try {
552                                 o = InternalInvoke (obj, parameters, out exc);
553 #if NET_2_1
554                         } catch (MethodAccessException) {
555                                 throw;
556 #endif
557                         } catch (Exception e) {
558                                 throw new TargetInvocationException (e);
559                         }
560
561                         if (exc != null)
562                                 throw exc;
563
564                         return obj == null ? o : null;
565                 }
566
567                 [DebuggerHidden]
568                 [DebuggerStepThrough]
569                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
570                 {
571                         return DoInvoke (null, invokeAttr, binder, parameters, culture);
572                 }
573
574                 public override RuntimeMethodHandle MethodHandle { 
575                         get {
576                                 return new RuntimeMethodHandle (mhandle);
577                         } 
578                 }
579                 
580                 public override MethodAttributes Attributes { 
581                         get {
582                                 return MonoMethodInfo.GetAttributes (mhandle);
583                         } 
584                 }
585
586                 public override CallingConventions CallingConvention { 
587                         get {
588                                 return MonoMethodInfo.GetCallingConvention (mhandle);
589                         }
590                 }
591                 
592                 public override Type ReflectedType {
593                         get {
594                                 return reftype;
595                         }
596                 }
597                 public override Type DeclaringType {
598                         get {
599                                 return MonoMethodInfo.GetDeclaringType (mhandle);
600                         }
601                 }
602                 public override string Name {
603                         get {
604                                 if (name != null)
605                                         return name;
606                                 return MonoMethod.get_name (this);
607                         }
608                 }
609
610                 public override bool IsDefined (Type attributeType, bool inherit) {
611                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
612                 }
613
614                 public override object[] GetCustomAttributes( bool inherit) {
615                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
616                 }
617
618                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
619                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
620                 }
621
622                 public override MethodBody GetMethodBody () {
623                         return GetMethodBody (mhandle);
624                 }
625
626                 public override string ToString () {
627                         StringBuilder sb = new StringBuilder ();
628                         sb.Append ("Void ");
629                         sb.Append (Name);
630                         sb.Append ("(");
631                         ParameterInfo[] p = GetParameters ();
632                         for (int i = 0; i < p.Length; ++i) {
633                                 if (i > 0)
634                                         sb.Append (", ");
635                                 sb.Append (p[i].ParameterType.Name);
636                         }
637                         if (CallingConvention == CallingConventions.Any)
638                                 sb.Append (", ...");
639                         sb.Append (")");
640                         return sb.ToString ();
641                 }
642
643                 // ISerializable
644                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
645                 {
646                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
647                 }
648
649 #if NET_4_0
650                 public override IList<CustomAttributeData> GetCustomAttributesData () {
651                         return CustomAttributeData.GetCustomAttributes (this);
652                 }
653 #endif
654         }
655 }