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;
44 using System.Diagnostics.Contracts;
46 namespace System.Reflection {
48 internal struct MonoMethodInfo
50 #pragma warning disable 649
53 internal MethodAttributes attrs;
54 internal MethodImplAttributes iattrs;
55 private CallingConventions callconv;
56 #pragma warning restore 649
58 [MethodImplAttribute(MethodImplOptions.InternalCall)]
59 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
61 [MethodImplAttribute(MethodImplOptions.InternalCall)]
62 static extern int get_method_attributes (IntPtr handle);
64 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
67 MonoMethodInfo.get_method_info (handle, out info);
71 internal static Type GetDeclaringType (IntPtr handle)
73 return GetMethodInfo (handle).parent;
76 internal static Type GetReturnType (IntPtr handle)
78 return GetMethodInfo (handle).ret;
81 internal static MethodAttributes GetAttributes (IntPtr handle)
83 return (MethodAttributes)get_method_attributes (handle);
86 internal static CallingConventions GetCallingConvention (IntPtr handle)
88 return GetMethodInfo (handle).callconv;
91 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
93 return GetMethodInfo (handle).iattrs;
96 [MethodImplAttribute(MethodImplOptions.InternalCall)]
97 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
99 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
101 return get_parameter_info (handle, member);
104 [MethodImplAttribute(MethodImplOptions.InternalCall)]
105 static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
107 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
109 return ParameterInfo.New (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
113 abstract class RuntimeMethodInfo : MethodInfo, ISerializable
115 internal BindingFlags BindingFlags {
121 RuntimeType ReflectedTypeInternal {
123 return (RuntimeType) ReflectedType;
127 internal override string FormatNameAndSig (bool serialization)
129 // Serialization uses ToString to resolve MethodInfo overloads.
130 StringBuilder sbName = new StringBuilder(Name);
132 // serialization == true: use unambiguous (except for assembly name) type names to distinguish between overloads.
133 // serialization == false: use basic format to maintain backward compatibility of MethodInfo.ToString().
134 TypeNameFormatFlags format = serialization ? TypeNameFormatFlags.FormatSerialization : TypeNameFormatFlags.FormatBasic;
137 sbName.Append(RuntimeMethodHandle.ConstructInstantiation(this, format));
140 ParameterInfo.FormatParameters (sbName, GetParametersNoCopy (), CallingConvention, serialization);
143 return sbName.ToString();
146 public override String ToString()
148 return ReturnType.FormatTypeName() + " " + FormatNameAndSig(false);
151 #region ISerializable Implementation
152 public void GetObjectData(SerializationInfo info, StreamingContext context)
155 throw new ArgumentNullException("info");
156 Contract.EndContractBlock();
158 MemberInfoSerializationHolder.GetSerializationInfo(
161 ReflectedTypeInternal,
163 SerializationToString(),
165 IsGenericMethod & !IsGenericMethodDefinition ? GetGenericArguments() : null);
168 internal string SerializationToString()
170 return ReturnType.FormatTypeName(true) + " " + FormatNameAndSig(true);
176 * Note: most of this class needs to be duplicated for the contructor, since
177 * the .NET reflection class hierarchy is so broken.
180 [StructLayout (LayoutKind.Sequential)]
181 internal class MonoMethod : RuntimeMethodInfo
183 #pragma warning disable 649
184 internal IntPtr mhandle;
187 #pragma warning restore 649
189 internal MonoMethod () {
192 internal MonoMethod (RuntimeMethodHandle mhandle) {
193 this.mhandle = mhandle.Value;
196 [MethodImplAttribute(MethodImplOptions.InternalCall)]
197 internal static extern string get_name (MethodBase method);
199 [MethodImplAttribute(MethodImplOptions.InternalCall)]
200 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
202 public override MethodInfo GetBaseDefinition ()
204 return get_base_method (this, true);
207 internal override MethodInfo GetBaseMethod ()
209 return get_base_method (this, false);
212 public override ParameterInfo ReturnParameter {
214 return MonoMethodInfo.GetReturnParameterInfo (this);
218 public override Type ReturnType {
220 return MonoMethodInfo.GetReturnType (mhandle);
223 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
225 return MonoMethodInfo.GetReturnParameterInfo (this);
229 public override MethodImplAttributes GetMethodImplementationFlags ()
231 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
234 public override ParameterInfo[] GetParameters ()
236 var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
240 // Have to clone because GetParametersInfo icall returns cached value
241 var dest = new ParameterInfo [src.Length];
242 Array.FastCopy (src, 0, dest, 0, src.Length);
246 internal override ParameterInfo[] GetParametersInternal ()
248 return MonoMethodInfo.GetParametersInfo (mhandle, this);
251 internal override int GetParametersCount ()
253 return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
257 * InternalInvoke() receives the parameters correctly converted by the
258 * binder to match the types of the method signature.
260 [MethodImplAttribute(MethodImplOptions.InternalCall)]
261 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
264 [DebuggerStepThrough]
265 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
268 binder = Type.DefaultBinder;
270 /*Avoid allocating an array every time*/
271 ParameterInfo[] pinfo = GetParametersInternal ();
272 ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
275 if (SecurityManager.SecurityEnabled) {
276 // sadly Attributes doesn't tell us which kind of security action this is so
277 // we must do it the hard way - and it also means that we can skip calling
278 // Attribute (which is another an icall)
279 SecurityManager.ReflectedLinkDemandInvoke (this);
283 if (ContainsGenericParameters)
284 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
290 // The ex argument is used to distinguish exceptions thrown by the icall
291 // from the exceptions thrown by the called method (which need to be
292 // wrapped in TargetInvocationException).
293 o = InternalInvoke (obj, parameters, out exc);
294 } catch (ThreadAbortException) {
297 } catch (MethodAccessException) {
300 } catch (Exception e) {
301 throw new TargetInvocationException (e);
309 internal static void ConvertValues (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture, BindingFlags invokeAttr)
312 if (pinfo.Length == 0)
315 throw new TargetParameterCountException ();
318 if (pinfo.Length != args.Length)
319 throw new TargetParameterCountException ();
321 for (int i = 0; i < args.Length; ++i) {
324 if (arg == Type.Missing) {
325 if (pi.DefaultValue == System.DBNull.Value)
326 throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters");
328 args [i] = pi.DefaultValue;
332 var rt = (RuntimeType) pi.ParameterType;
333 args [i] = rt.CheckValue (arg, binder, culture, invokeAttr);
337 public override RuntimeMethodHandle MethodHandle {
339 return new RuntimeMethodHandle (mhandle);
343 public override MethodAttributes Attributes {
345 return MonoMethodInfo.GetAttributes (mhandle);
349 public override CallingConventions CallingConvention {
351 return MonoMethodInfo.GetCallingConvention (mhandle);
355 public override Type ReflectedType {
360 public override Type DeclaringType {
362 return MonoMethodInfo.GetDeclaringType (mhandle);
365 public override string Name {
369 return get_name (this);
373 public override bool IsDefined (Type attributeType, bool inherit) {
374 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
377 public override object[] GetCustomAttributes( bool inherit) {
378 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
380 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
381 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
384 [MethodImplAttribute(MethodImplOptions.InternalCall)]
385 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
387 internal object[] GetPseudoCustomAttributes ()
391 /* MS.NET doesn't report MethodImplAttribute */
393 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
394 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
396 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
401 object[] attrs = new object [count];
404 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
405 attrs [count ++] = new PreserveSigAttribute ();
406 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
407 DllImportAttribute attr = GetDllImportAttribute (mhandle);
408 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
409 attr.PreserveSig = true;
410 attrs [count ++] = attr;
416 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
418 if (methodInstantiation == null)
419 throw new ArgumentNullException ("methodInstantiation");
421 if (!IsGenericMethodDefinition)
422 throw new InvalidOperationException ("not a generic method definition");
424 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
425 if (GetGenericArguments ().Length != methodInstantiation.Length)
426 throw new ArgumentException ("Incorrect length");
428 bool hasUserType = false;
429 foreach (Type type in methodInstantiation) {
431 throw new ArgumentNullException ();
432 if (!(type is MonoType))
438 throw new NotSupportedException ("User types are not supported under full aot");
440 return new MethodOnTypeBuilderInst (this, methodInstantiation);
443 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
445 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
449 [MethodImplAttribute(MethodImplOptions.InternalCall)]
450 extern MethodInfo MakeGenericMethod_impl (Type [] types);
452 [MethodImplAttribute(MethodImplOptions.InternalCall)]
453 public override extern Type [] GetGenericArguments ();
455 [MethodImplAttribute(MethodImplOptions.InternalCall)]
456 extern MethodInfo GetGenericMethodDefinition_impl ();
458 public override MethodInfo GetGenericMethodDefinition ()
460 MethodInfo res = GetGenericMethodDefinition_impl ();
462 throw new InvalidOperationException ();
467 public override extern bool IsGenericMethodDefinition {
468 [MethodImplAttribute(MethodImplOptions.InternalCall)]
472 public override extern bool IsGenericMethod {
473 [MethodImplAttribute(MethodImplOptions.InternalCall)]
477 public override bool ContainsGenericParameters {
479 if (IsGenericMethod) {
480 foreach (Type arg in GetGenericArguments ())
481 if (arg.ContainsGenericParameters)
484 return DeclaringType.ContainsGenericParameters;
488 public override MethodBody GetMethodBody () {
489 return GetMethodBody (mhandle);
492 public override IList<CustomAttributeData> GetCustomAttributesData () {
493 return CustomAttributeData.GetCustomAttributes (this);
496 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
497 [MethodImplAttribute(MethodImplOptions.InternalCall)]
498 public extern int get_core_clr_security_level ();
500 public override bool IsSecurityTransparent {
501 get { return get_core_clr_security_level () == 0; }
504 public override bool IsSecurityCritical {
505 get { return get_core_clr_security_level () > 0; }
508 public override bool IsSecuritySafeCritical {
509 get { return get_core_clr_security_level () == 1; }
514 abstract class RuntimeConstructorInfo : ConstructorInfo, ISerializable
516 public override Module Module {
518 return GetRuntimeModule ();
522 internal RuntimeModule GetRuntimeModule ()
524 return RuntimeTypeHandle.GetModule((RuntimeType)DeclaringType);
527 internal BindingFlags BindingFlags {
533 RuntimeType ReflectedTypeInternal {
535 return (RuntimeType) ReflectedType;
539 #region ISerializable Implementation
540 public void GetObjectData(SerializationInfo info, StreamingContext context)
543 throw new ArgumentNullException("info");
544 Contract.EndContractBlock();
545 MemberInfoSerializationHolder.GetSerializationInfo(
548 ReflectedTypeInternal,
550 SerializationToString(),
551 MemberTypes.Constructor,
555 internal string SerializationToString()
557 // We don't need the return type for constructors.
558 return FormatNameAndSig(true);
561 internal void SerializationInvoke (Object target, SerializationInfo info, StreamingContext context)
563 Invoke (target, new object[] { info, context });
569 [StructLayout (LayoutKind.Sequential)]
570 internal class MonoCMethod : RuntimeConstructorInfo
572 #pragma warning disable 649
573 internal IntPtr mhandle;
576 #pragma warning restore 649
578 public override MethodImplAttributes GetMethodImplementationFlags ()
580 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
583 public override ParameterInfo[] GetParameters ()
585 return MonoMethodInfo.GetParametersInfo (mhandle, this);
588 internal override ParameterInfo[] GetParametersInternal ()
590 return MonoMethodInfo.GetParametersInfo (mhandle, this);
593 internal override int GetParametersCount ()
595 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
596 return pi == null ? 0 : pi.Length;
600 * InternalInvoke() receives the parameters correctly converted by the binder
601 * to match the types of the method signature.
603 [MethodImplAttribute(MethodImplOptions.InternalCall)]
604 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
607 [DebuggerStepThrough]
608 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
612 throw new TargetException ("Instance constructor requires a target");
613 } else if (!DeclaringType.IsInstanceOfType (obj)) {
614 throw new TargetException ("Constructor does not match target type");
617 return DoInvoke (obj, invokeAttr, binder, parameters, culture);
620 object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
623 binder = Type.DefaultBinder;
625 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
627 MonoMethod.ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
630 if (SecurityManager.SecurityEnabled) {
631 // sadly Attributes doesn't tell us which kind of security action this is so
632 // we must do it the hard way - and it also means that we can skip calling
633 // Attribute (which is another an icall)
634 SecurityManager.ReflectedLinkDemandInvoke (this);
638 if (obj == null && DeclaringType.ContainsGenericParameters)
639 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
641 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
642 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
645 return InternalInvoke (obj, parameters);
648 public object InternalInvoke (object obj, object[] parameters)
654 o = InternalInvoke (obj, parameters, out exc);
656 } catch (MethodAccessException) {
659 } catch (Exception e) {
660 throw new TargetInvocationException (e);
666 return obj == null ? o : null;
670 [DebuggerStepThrough]
671 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
673 return DoInvoke (null, invokeAttr, binder, parameters, culture);
676 public override RuntimeMethodHandle MethodHandle {
678 return new RuntimeMethodHandle (mhandle);
682 public override MethodAttributes Attributes {
684 return MonoMethodInfo.GetAttributes (mhandle);
688 public override CallingConventions CallingConvention {
690 return MonoMethodInfo.GetCallingConvention (mhandle);
694 public override bool ContainsGenericParameters {
696 return DeclaringType.ContainsGenericParameters;
700 public override Type ReflectedType {
705 public override Type DeclaringType {
707 return MonoMethodInfo.GetDeclaringType (mhandle);
710 public override string Name {
714 return MonoMethod.get_name (this);
718 public override bool IsDefined (Type attributeType, bool inherit) {
719 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
722 public override object[] GetCustomAttributes( bool inherit) {
723 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
726 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
727 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
730 public override MethodBody GetMethodBody () {
731 return GetMethodBody (mhandle);
734 public override string ToString () {
735 StringBuilder sb = new StringBuilder ();
739 ParameterInfo[] p = GetParameters ();
740 for (int i = 0; i < p.Length; ++i) {
743 sb.Append (p[i].ParameterType.Name);
745 if (CallingConvention == CallingConventions.Any)
748 return sb.ToString ();
751 public override IList<CustomAttributeData> GetCustomAttributesData () {
752 return CustomAttributeData.GetCustomAttributes (this);