2 // MonoMethod.cs: The class used to represent methods from the mono runtime.
5 // Paolo Molaro (lupus@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
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)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
32 using System.Collections.Generic;
33 using System.Globalization;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Runtime.Serialization;
38 using System.Reflection.Emit;
40 using System.Security;
41 using System.Threading;
43 using System.Diagnostics;
45 namespace System.Reflection {
47 internal struct MonoMethodInfo
49 #pragma warning disable 649
52 internal MethodAttributes attrs;
53 internal MethodImplAttributes iattrs;
54 private CallingConventions callconv;
55 #pragma warning restore 649
57 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
60 [MethodImplAttribute(MethodImplOptions.InternalCall)]
61 static extern int get_method_attributes (IntPtr handle);
63 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
66 MonoMethodInfo.get_method_info (handle, out info);
70 internal static Type GetDeclaringType (IntPtr handle)
72 return GetMethodInfo (handle).parent;
75 internal static Type GetReturnType (IntPtr handle)
77 return GetMethodInfo (handle).ret;
80 internal static MethodAttributes GetAttributes (IntPtr handle)
82 return (MethodAttributes)get_method_attributes (handle);
85 internal static CallingConventions GetCallingConvention (IntPtr handle)
87 return GetMethodInfo (handle).callconv;
90 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
92 return GetMethodInfo (handle).iattrs;
95 [MethodImplAttribute(MethodImplOptions.InternalCall)]
96 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
98 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
100 return get_parameter_info (handle, member);
103 [MethodImplAttribute(MethodImplOptions.InternalCall)]
104 static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
106 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
108 return ParameterInfo.New (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
112 abstract class RuntimeMethodInfo : MethodInfo
117 * Note: most of this class needs to be duplicated for the contructor, since
118 * the .NET reflection class hierarchy is so broken.
121 [StructLayout (LayoutKind.Sequential)]
122 internal class MonoMethod : RuntimeMethodInfo, ISerializable
124 #pragma warning disable 649
125 internal IntPtr mhandle;
128 #pragma warning restore 649
130 internal MonoMethod () {
133 internal MonoMethod (RuntimeMethodHandle mhandle) {
134 this.mhandle = mhandle.Value;
137 [MethodImplAttribute(MethodImplOptions.InternalCall)]
138 internal static extern string get_name (MethodBase method);
140 [MethodImplAttribute(MethodImplOptions.InternalCall)]
141 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
143 public override MethodInfo GetBaseDefinition ()
145 return get_base_method (this, true);
148 internal override MethodInfo GetBaseMethod ()
150 return get_base_method (this, false);
153 public override ParameterInfo ReturnParameter {
155 return MonoMethodInfo.GetReturnParameterInfo (this);
159 public override Type ReturnType {
161 return MonoMethodInfo.GetReturnType (mhandle);
164 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
166 return MonoMethodInfo.GetReturnParameterInfo (this);
170 public override MethodImplAttributes GetMethodImplementationFlags ()
172 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
175 public override ParameterInfo[] GetParameters ()
177 var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
181 // Have to clone because GetParametersInfo icall returns cached value
182 var dest = new ParameterInfo [src.Length];
183 Array.FastCopy (src, 0, dest, 0, src.Length);
187 internal override ParameterInfo[] GetParametersInternal ()
189 return MonoMethodInfo.GetParametersInfo (mhandle, this);
192 internal override int GetParametersCount ()
194 return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
198 * InternalInvoke() receives the parameters correctly converted by the
199 * binder to match the types of the method signature.
201 [MethodImplAttribute(MethodImplOptions.InternalCall)]
202 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
205 [DebuggerStepThrough]
206 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
209 binder = Type.DefaultBinder;
211 /*Avoid allocating an array every time*/
212 ParameterInfo[] pinfo = GetParametersInternal ();
213 ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
216 if (SecurityManager.SecurityEnabled) {
217 // sadly Attributes doesn't tell us which kind of security action this is so
218 // we must do it the hard way - and it also means that we can skip calling
219 // Attribute (which is another an icall)
220 SecurityManager.ReflectedLinkDemandInvoke (this);
224 if (ContainsGenericParameters)
225 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
231 // The ex argument is used to distinguish exceptions thrown by the icall
232 // from the exceptions thrown by the called method (which need to be
233 // wrapped in TargetInvocationException).
234 o = InternalInvoke (obj, parameters, out exc);
235 } catch (ThreadAbortException) {
238 } catch (MethodAccessException) {
241 } catch (Exception e) {
242 throw new TargetInvocationException (e);
250 internal static void ConvertValues (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture, BindingFlags invokeAttr)
253 if (pinfo.Length == 0)
256 throw new TargetParameterCountException ();
259 if (pinfo.Length != args.Length)
260 throw new TargetParameterCountException ();
262 for (int i = 0; i < args.Length; ++i) {
265 if (arg == Type.Missing) {
266 args [i] = pi.DefaultValue;
270 var rt = (RuntimeType) pi.ParameterType;
271 args [i] = rt.CheckValue (arg, binder, culture, invokeAttr);
275 public override RuntimeMethodHandle MethodHandle {
277 return new RuntimeMethodHandle (mhandle);
281 public override MethodAttributes Attributes {
283 return MonoMethodInfo.GetAttributes (mhandle);
287 public override CallingConventions CallingConvention {
289 return MonoMethodInfo.GetCallingConvention (mhandle);
293 public override Type ReflectedType {
298 public override Type DeclaringType {
300 return MonoMethodInfo.GetDeclaringType (mhandle);
303 public override string Name {
307 return get_name (this);
311 public override bool IsDefined (Type attributeType, bool inherit) {
312 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
315 public override object[] GetCustomAttributes( bool inherit) {
316 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
318 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
319 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
322 [MethodImplAttribute(MethodImplOptions.InternalCall)]
323 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
325 internal object[] GetPseudoCustomAttributes ()
329 /* MS.NET doesn't report MethodImplAttribute */
331 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
332 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
334 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
339 object[] attrs = new object [count];
342 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
343 attrs [count ++] = new PreserveSigAttribute ();
344 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
345 DllImportAttribute attr = GetDllImportAttribute (mhandle);
346 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
347 attr.PreserveSig = true;
348 attrs [count ++] = attr;
354 public override string ToString () {
355 StringBuilder sb = new StringBuilder ();
356 Type retType = ReturnType;
357 if (Type.ShouldPrintFullName (retType))
358 sb.Append (retType.ToString ());
360 sb.Append (retType.Name);
363 if (IsGenericMethod) {
364 Type[] gen_params = GetGenericArguments ();
366 for (int j = 0; j < gen_params.Length; j++) {
369 sb.Append (gen_params [j].Name);
375 var p = GetParametersInternal ();
376 ParameterInfo.FormatParameters (sb, p);
378 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
385 return sb.ToString ();
390 public void GetObjectData(SerializationInfo info, StreamingContext context)
392 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
393 ? GetGenericArguments () : null;
394 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
397 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
399 if (methodInstantiation == null)
400 throw new ArgumentNullException ("methodInstantiation");
402 if (!IsGenericMethodDefinition)
403 throw new InvalidOperationException ("not a generic method definition");
405 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
406 if (GetGenericArguments ().Length != methodInstantiation.Length)
407 throw new ArgumentException ("Incorrect length");
409 bool hasUserType = false;
410 foreach (Type type in methodInstantiation) {
412 throw new ArgumentNullException ();
413 if (!(type is MonoType))
419 throw new NotSupportedException ("User types are not supported under full aot");
421 return new MethodOnTypeBuilderInst (this, methodInstantiation);
424 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
426 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
430 [MethodImplAttribute(MethodImplOptions.InternalCall)]
431 extern MethodInfo MakeGenericMethod_impl (Type [] types);
433 [MethodImplAttribute(MethodImplOptions.InternalCall)]
434 public override extern Type [] GetGenericArguments ();
436 [MethodImplAttribute(MethodImplOptions.InternalCall)]
437 extern MethodInfo GetGenericMethodDefinition_impl ();
439 public override MethodInfo GetGenericMethodDefinition ()
441 MethodInfo res = GetGenericMethodDefinition_impl ();
443 throw new InvalidOperationException ();
448 public override extern bool IsGenericMethodDefinition {
449 [MethodImplAttribute(MethodImplOptions.InternalCall)]
453 public override extern bool IsGenericMethod {
454 [MethodImplAttribute(MethodImplOptions.InternalCall)]
458 public override bool ContainsGenericParameters {
460 if (IsGenericMethod) {
461 foreach (Type arg in GetGenericArguments ())
462 if (arg.ContainsGenericParameters)
465 return DeclaringType.ContainsGenericParameters;
469 public override MethodBody GetMethodBody () {
470 return GetMethodBody (mhandle);
473 public override IList<CustomAttributeData> GetCustomAttributesData () {
474 return CustomAttributeData.GetCustomAttributes (this);
479 abstract class RuntimeConstructorInfo : ConstructorInfo
484 [StructLayout (LayoutKind.Sequential)]
485 internal class MonoCMethod : RuntimeConstructorInfo, ISerializable
487 #pragma warning disable 649
488 internal IntPtr mhandle;
491 #pragma warning restore 649
493 public override MethodImplAttributes GetMethodImplementationFlags ()
495 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
498 public override ParameterInfo[] GetParameters ()
500 return MonoMethodInfo.GetParametersInfo (mhandle, this);
503 internal override ParameterInfo[] GetParametersInternal ()
505 return MonoMethodInfo.GetParametersInfo (mhandle, this);
508 internal override int GetParametersCount ()
510 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
511 return pi == null ? 0 : pi.Length;
515 * InternalInvoke() receives the parameters correctly converted by the binder
516 * to match the types of the method signature.
518 [MethodImplAttribute(MethodImplOptions.InternalCall)]
519 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
522 [DebuggerStepThrough]
523 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
527 throw new TargetException ("Instance constructor requires a target");
528 } else if (!DeclaringType.IsInstanceOfType (obj)) {
529 throw new TargetException ("Constructor does not match target type");
532 return DoInvoke (obj, invokeAttr, binder, parameters, culture);
535 object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
538 binder = Type.DefaultBinder;
540 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
542 MonoMethod.ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
545 if (SecurityManager.SecurityEnabled) {
546 // sadly Attributes doesn't tell us which kind of security action this is so
547 // we must do it the hard way - and it also means that we can skip calling
548 // Attribute (which is another an icall)
549 SecurityManager.ReflectedLinkDemandInvoke (this);
553 if (obj == null && DeclaringType.ContainsGenericParameters)
554 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
556 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
557 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
560 return InternalInvoke (obj, parameters);
563 public object InternalInvoke (object obj, object[] parameters)
569 o = InternalInvoke (obj, parameters, out exc);
571 } catch (MethodAccessException) {
574 } catch (Exception e) {
575 throw new TargetInvocationException (e);
581 return obj == null ? o : null;
585 [DebuggerStepThrough]
586 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
588 return DoInvoke (null, invokeAttr, binder, parameters, culture);
591 public override RuntimeMethodHandle MethodHandle {
593 return new RuntimeMethodHandle (mhandle);
597 public override MethodAttributes Attributes {
599 return MonoMethodInfo.GetAttributes (mhandle);
603 public override CallingConventions CallingConvention {
605 return MonoMethodInfo.GetCallingConvention (mhandle);
609 public override bool ContainsGenericParameters {
611 return DeclaringType.ContainsGenericParameters;
615 public override Type ReflectedType {
620 public override Type DeclaringType {
622 return MonoMethodInfo.GetDeclaringType (mhandle);
625 public override string Name {
629 return MonoMethod.get_name (this);
633 public override bool IsDefined (Type attributeType, bool inherit) {
634 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
637 public override object[] GetCustomAttributes( bool inherit) {
638 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
641 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
642 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
645 public override MethodBody GetMethodBody () {
646 return GetMethodBody (mhandle);
649 public override string ToString () {
650 StringBuilder sb = new StringBuilder ();
654 ParameterInfo[] p = GetParameters ();
655 for (int i = 0; i < p.Length; ++i) {
658 sb.Append (p[i].ParameterType.Name);
660 if (CallingConvention == CallingConventions.Any)
663 return sb.ToString ();
667 public void GetObjectData(SerializationInfo info, StreamingContext context)
669 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
672 public override IList<CustomAttributeData> GetCustomAttributesData () {
673 return CustomAttributeData.GetCustomAttributes (this);