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
114 internal BindingFlags BindingFlags {
122 * Note: most of this class needs to be duplicated for the contructor, since
123 * the .NET reflection class hierarchy is so broken.
126 [StructLayout (LayoutKind.Sequential)]
127 internal class MonoMethod : RuntimeMethodInfo, ISerializable
129 #pragma warning disable 649
130 internal IntPtr mhandle;
133 #pragma warning restore 649
135 internal MonoMethod () {
138 internal MonoMethod (RuntimeMethodHandle mhandle) {
139 this.mhandle = mhandle.Value;
142 [MethodImplAttribute(MethodImplOptions.InternalCall)]
143 internal static extern string get_name (MethodBase method);
145 [MethodImplAttribute(MethodImplOptions.InternalCall)]
146 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
148 public override MethodInfo GetBaseDefinition ()
150 return get_base_method (this, true);
153 internal override MethodInfo GetBaseMethod ()
155 return get_base_method (this, false);
158 public override ParameterInfo ReturnParameter {
160 return MonoMethodInfo.GetReturnParameterInfo (this);
164 public override Type ReturnType {
166 return MonoMethodInfo.GetReturnType (mhandle);
169 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
171 return MonoMethodInfo.GetReturnParameterInfo (this);
175 public override MethodImplAttributes GetMethodImplementationFlags ()
177 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
180 public override ParameterInfo[] GetParameters ()
182 var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
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);
192 internal override ParameterInfo[] GetParametersInternal ()
194 return MonoMethodInfo.GetParametersInfo (mhandle, this);
197 internal override int GetParametersCount ()
199 return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
203 * InternalInvoke() receives the parameters correctly converted by the
204 * binder to match the types of the method signature.
206 [MethodImplAttribute(MethodImplOptions.InternalCall)]
207 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
210 [DebuggerStepThrough]
211 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
214 binder = Type.DefaultBinder;
216 /*Avoid allocating an array every time*/
217 ParameterInfo[] pinfo = GetParametersInternal ();
218 ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
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);
229 if (ContainsGenericParameters)
230 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
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) {
243 } catch (MethodAccessException) {
246 } catch (Exception e) {
247 throw new TargetInvocationException (e);
255 internal static void ConvertValues (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture, BindingFlags invokeAttr)
258 if (pinfo.Length == 0)
261 throw new TargetParameterCountException ();
264 if (pinfo.Length != args.Length)
265 throw new TargetParameterCountException ();
267 for (int i = 0; i < args.Length; ++i) {
270 if (arg == Type.Missing) {
271 if (pi.DefaultValue == System.DBNull.Value)
272 throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters");
274 args [i] = pi.DefaultValue;
278 var rt = (RuntimeType) pi.ParameterType;
279 args [i] = rt.CheckValue (arg, binder, culture, invokeAttr);
283 public override RuntimeMethodHandle MethodHandle {
285 return new RuntimeMethodHandle (mhandle);
289 public override MethodAttributes Attributes {
291 return MonoMethodInfo.GetAttributes (mhandle);
295 public override CallingConventions CallingConvention {
297 return MonoMethodInfo.GetCallingConvention (mhandle);
301 public override Type ReflectedType {
306 public override Type DeclaringType {
308 return MonoMethodInfo.GetDeclaringType (mhandle);
311 public override string Name {
315 return get_name (this);
319 public override bool IsDefined (Type attributeType, bool inherit) {
320 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
323 public override object[] GetCustomAttributes( bool inherit) {
324 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
326 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
327 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
330 [MethodImplAttribute(MethodImplOptions.InternalCall)]
331 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
333 internal object[] GetPseudoCustomAttributes ()
337 /* MS.NET doesn't report MethodImplAttribute */
339 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
340 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
342 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
347 object[] attrs = new object [count];
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;
362 public override string ToString () {
363 StringBuilder sb = new StringBuilder ();
364 Type retType = ReturnType;
365 if (Type.ShouldPrintFullName (retType))
366 sb.Append (retType.ToString ());
368 sb.Append (retType.Name);
371 if (IsGenericMethod) {
372 Type[] gen_params = GetGenericArguments ();
374 for (int j = 0; j < gen_params.Length; j++) {
377 sb.Append (gen_params [j].Name);
383 var p = GetParametersInternal ();
384 ParameterInfo.FormatParameters (sb, p);
386 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
393 return sb.ToString ();
398 public void GetObjectData(SerializationInfo info, StreamingContext context)
400 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
401 ? GetGenericArguments () : null;
402 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
405 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
407 if (methodInstantiation == null)
408 throw new ArgumentNullException ("methodInstantiation");
410 if (!IsGenericMethodDefinition)
411 throw new InvalidOperationException ("not a generic method definition");
413 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
414 if (GetGenericArguments ().Length != methodInstantiation.Length)
415 throw new ArgumentException ("Incorrect length");
417 bool hasUserType = false;
418 foreach (Type type in methodInstantiation) {
420 throw new ArgumentNullException ();
421 if (!(type is MonoType))
427 throw new NotSupportedException ("User types are not supported under full aot");
429 return new MethodOnTypeBuilderInst (this, methodInstantiation);
432 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
434 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
438 [MethodImplAttribute(MethodImplOptions.InternalCall)]
439 extern MethodInfo MakeGenericMethod_impl (Type [] types);
441 [MethodImplAttribute(MethodImplOptions.InternalCall)]
442 public override extern Type [] GetGenericArguments ();
444 [MethodImplAttribute(MethodImplOptions.InternalCall)]
445 extern MethodInfo GetGenericMethodDefinition_impl ();
447 public override MethodInfo GetGenericMethodDefinition ()
449 MethodInfo res = GetGenericMethodDefinition_impl ();
451 throw new InvalidOperationException ();
456 public override extern bool IsGenericMethodDefinition {
457 [MethodImplAttribute(MethodImplOptions.InternalCall)]
461 public override extern bool IsGenericMethod {
462 [MethodImplAttribute(MethodImplOptions.InternalCall)]
466 public override bool ContainsGenericParameters {
468 if (IsGenericMethod) {
469 foreach (Type arg in GetGenericArguments ())
470 if (arg.ContainsGenericParameters)
473 return DeclaringType.ContainsGenericParameters;
477 public override MethodBody GetMethodBody () {
478 return GetMethodBody (mhandle);
481 public override IList<CustomAttributeData> GetCustomAttributesData () {
482 return CustomAttributeData.GetCustomAttributes (this);
487 abstract class RuntimeConstructorInfo : ConstructorInfo
489 internal BindingFlags BindingFlags {
497 [StructLayout (LayoutKind.Sequential)]
498 internal class MonoCMethod : RuntimeConstructorInfo, ISerializable
500 #pragma warning disable 649
501 internal IntPtr mhandle;
504 #pragma warning restore 649
506 public override MethodImplAttributes GetMethodImplementationFlags ()
508 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
511 public override ParameterInfo[] GetParameters ()
513 return MonoMethodInfo.GetParametersInfo (mhandle, this);
516 internal override ParameterInfo[] GetParametersInternal ()
518 return MonoMethodInfo.GetParametersInfo (mhandle, this);
521 internal override int GetParametersCount ()
523 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
524 return pi == null ? 0 : pi.Length;
528 * InternalInvoke() receives the parameters correctly converted by the binder
529 * to match the types of the method signature.
531 [MethodImplAttribute(MethodImplOptions.InternalCall)]
532 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
535 [DebuggerStepThrough]
536 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
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");
545 return DoInvoke (obj, invokeAttr, binder, parameters, culture);
548 object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
551 binder = Type.DefaultBinder;
553 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
555 MonoMethod.ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
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);
566 if (obj == null && DeclaringType.ContainsGenericParameters)
567 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
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));
573 return InternalInvoke (obj, parameters);
576 public object InternalInvoke (object obj, object[] parameters)
582 o = InternalInvoke (obj, parameters, out exc);
584 } catch (MethodAccessException) {
587 } catch (Exception e) {
588 throw new TargetInvocationException (e);
594 return obj == null ? o : null;
598 [DebuggerStepThrough]
599 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
601 return DoInvoke (null, invokeAttr, binder, parameters, culture);
604 public override RuntimeMethodHandle MethodHandle {
606 return new RuntimeMethodHandle (mhandle);
610 public override MethodAttributes Attributes {
612 return MonoMethodInfo.GetAttributes (mhandle);
616 public override CallingConventions CallingConvention {
618 return MonoMethodInfo.GetCallingConvention (mhandle);
622 public override bool ContainsGenericParameters {
624 return DeclaringType.ContainsGenericParameters;
628 public override Type ReflectedType {
633 public override Type DeclaringType {
635 return MonoMethodInfo.GetDeclaringType (mhandle);
638 public override string Name {
642 return MonoMethod.get_name (this);
646 public override bool IsDefined (Type attributeType, bool inherit) {
647 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
650 public override object[] GetCustomAttributes( bool inherit) {
651 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
654 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
655 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
658 public override MethodBody GetMethodBody () {
659 return GetMethodBody (mhandle);
662 public override string ToString () {
663 StringBuilder sb = new StringBuilder ();
667 ParameterInfo[] p = GetParameters ();
668 for (int i = 0; i < p.Length; ++i) {
671 sb.Append (p[i].ParameterType.Name);
673 if (CallingConvention == CallingConventions.Any)
676 return sb.ToString ();
680 public void GetObjectData(SerializationInfo info, StreamingContext context)
682 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
685 public override IList<CustomAttributeData> GetCustomAttributesData () {
686 return CustomAttributeData.GetCustomAttributes (this);