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 public override Module Module {
123 return GetRuntimeModule ();
127 RuntimeType ReflectedTypeInternal {
129 return (RuntimeType) ReflectedType;
133 internal override string FormatNameAndSig (bool serialization)
135 // Serialization uses ToString to resolve MethodInfo overloads.
136 StringBuilder sbName = new StringBuilder(Name);
138 // serialization == true: use unambiguous (except for assembly name) type names to distinguish between overloads.
139 // serialization == false: use basic format to maintain backward compatibility of MethodInfo.ToString().
140 TypeNameFormatFlags format = serialization ? TypeNameFormatFlags.FormatSerialization : TypeNameFormatFlags.FormatBasic;
143 sbName.Append(RuntimeMethodHandle.ConstructInstantiation(this, format));
146 ParameterInfo.FormatParameters (sbName, GetParametersNoCopy (), CallingConvention, serialization);
149 return sbName.ToString();
152 public override Delegate CreateDelegate (Type delegateType)
154 return Delegate.CreateDelegate (delegateType, this);
157 public override Delegate CreateDelegate (Type delegateType, object target)
159 return Delegate.CreateDelegate (delegateType, target, this);
162 public override String ToString()
164 return ReturnType.FormatTypeName() + " " + FormatNameAndSig(false);
167 internal RuntimeModule GetRuntimeModule ()
169 return ((RuntimeType)DeclaringType).GetRuntimeModule();
172 #region ISerializable Implementation
173 public void GetObjectData(SerializationInfo info, StreamingContext context)
176 throw new ArgumentNullException("info");
177 Contract.EndContractBlock();
179 MemberInfoSerializationHolder.GetSerializationInfo(
182 ReflectedTypeInternal,
184 SerializationToString(),
186 IsGenericMethod & !IsGenericMethodDefinition ? GetGenericArguments() : null);
189 internal string SerializationToString()
191 return ReturnType.FormatTypeName(true) + " " + FormatNameAndSig(true);
197 * Note: most of this class needs to be duplicated for the contructor, since
198 * the .NET reflection class hierarchy is so broken.
201 [StructLayout (LayoutKind.Sequential)]
202 internal class MonoMethod : RuntimeMethodInfo
204 #pragma warning disable 649
205 internal IntPtr mhandle;
208 #pragma warning restore 649
210 internal MonoMethod () {
213 internal MonoMethod (RuntimeMethodHandle mhandle) {
214 this.mhandle = mhandle.Value;
217 [MethodImplAttribute(MethodImplOptions.InternalCall)]
218 internal static extern string get_name (MethodBase method);
220 [MethodImplAttribute(MethodImplOptions.InternalCall)]
221 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
223 public override MethodInfo GetBaseDefinition ()
225 return get_base_method (this, true);
228 internal override MethodInfo GetBaseMethod ()
230 return get_base_method (this, false);
233 public override ParameterInfo ReturnParameter {
235 return MonoMethodInfo.GetReturnParameterInfo (this);
239 public override Type ReturnType {
241 return MonoMethodInfo.GetReturnType (mhandle);
244 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
246 return MonoMethodInfo.GetReturnParameterInfo (this);
250 public override MethodImplAttributes GetMethodImplementationFlags ()
252 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
255 public override ParameterInfo[] GetParameters ()
257 var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
261 // Have to clone because GetParametersInfo icall returns cached value
262 var dest = new ParameterInfo [src.Length];
263 Array.FastCopy (src, 0, dest, 0, src.Length);
267 internal override ParameterInfo[] GetParametersInternal ()
269 return MonoMethodInfo.GetParametersInfo (mhandle, this);
272 internal override int GetParametersCount ()
274 return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
278 * InternalInvoke() receives the parameters correctly converted by the
279 * binder to match the types of the method signature.
281 [MethodImplAttribute(MethodImplOptions.InternalCall)]
282 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
285 [DebuggerStepThrough]
286 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
289 binder = Type.DefaultBinder;
291 /*Avoid allocating an array every time*/
292 ParameterInfo[] pinfo = GetParametersInternal ();
293 ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
295 if (ContainsGenericParameters)
296 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
302 // The ex argument is used to distinguish exceptions thrown by the icall
303 // from the exceptions thrown by the called method (which need to be
304 // wrapped in TargetInvocationException).
305 o = InternalInvoke (obj, parameters, out exc);
306 } catch (ThreadAbortException) {
309 } catch (MethodAccessException) {
312 } catch (Exception e) {
313 throw new TargetInvocationException (e);
321 internal static void ConvertValues (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture, BindingFlags invokeAttr)
324 if (pinfo.Length == 0)
327 throw new TargetParameterCountException ();
330 if (pinfo.Length != args.Length)
331 throw new TargetParameterCountException ();
333 for (int i = 0; i < args.Length; ++i) {
336 if (arg == Type.Missing) {
337 if (pi.DefaultValue == System.DBNull.Value)
338 throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters");
340 args [i] = pi.DefaultValue;
344 var rt = (RuntimeType) pi.ParameterType;
345 args [i] = rt.CheckValue (arg, binder, culture, invokeAttr);
349 public override RuntimeMethodHandle MethodHandle {
351 return new RuntimeMethodHandle (mhandle);
355 public override MethodAttributes Attributes {
357 return MonoMethodInfo.GetAttributes (mhandle);
361 public override CallingConventions CallingConvention {
363 return MonoMethodInfo.GetCallingConvention (mhandle);
367 public override Type ReflectedType {
372 public override Type DeclaringType {
374 return MonoMethodInfo.GetDeclaringType (mhandle);
377 public override string Name {
381 return get_name (this);
385 public override bool IsDefined (Type attributeType, bool inherit) {
386 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
389 public override object[] GetCustomAttributes( bool inherit) {
390 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
392 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
393 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
396 [MethodImplAttribute(MethodImplOptions.InternalCall)]
397 internal extern void GetPInvoke (out PInvokeAttributes flags, out string entryPoint, out string dllName);
399 internal object[] GetPseudoCustomAttributes ()
403 /* MS.NET doesn't report MethodImplAttribute */
405 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
406 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
408 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
413 object[] attrs = new object [count];
416 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
417 attrs [count ++] = new PreserveSigAttribute ();
418 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
419 attrs [count ++] = DllImportAttribute.GetCustomAttribute (this);
425 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
427 if (methodInstantiation == null)
428 throw new ArgumentNullException ("methodInstantiation");
430 if (!IsGenericMethodDefinition)
431 throw new InvalidOperationException ("not a generic method definition");
433 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
434 if (GetGenericArguments ().Length != methodInstantiation.Length)
435 throw new ArgumentException ("Incorrect length");
437 bool hasUserType = false;
438 foreach (Type type in methodInstantiation) {
440 throw new ArgumentNullException ();
441 if (!(type is MonoType))
447 throw new NotSupportedException ("User types are not supported under full aot");
449 return new MethodOnTypeBuilderInst (this, methodInstantiation);
452 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
454 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
458 [MethodImplAttribute(MethodImplOptions.InternalCall)]
459 extern MethodInfo MakeGenericMethod_impl (Type [] types);
461 [MethodImplAttribute(MethodImplOptions.InternalCall)]
462 public override extern Type [] GetGenericArguments ();
464 [MethodImplAttribute(MethodImplOptions.InternalCall)]
465 extern MethodInfo GetGenericMethodDefinition_impl ();
467 public override MethodInfo GetGenericMethodDefinition ()
469 MethodInfo res = GetGenericMethodDefinition_impl ();
471 throw new InvalidOperationException ();
476 public override extern bool IsGenericMethodDefinition {
477 [MethodImplAttribute(MethodImplOptions.InternalCall)]
481 public override extern bool IsGenericMethod {
482 [MethodImplAttribute(MethodImplOptions.InternalCall)]
486 public override bool ContainsGenericParameters {
488 if (IsGenericMethod) {
489 foreach (Type arg in GetGenericArguments ())
490 if (arg.ContainsGenericParameters)
493 return DeclaringType.ContainsGenericParameters;
497 public override MethodBody GetMethodBody () {
498 return GetMethodBody (mhandle);
501 public override IList<CustomAttributeData> GetCustomAttributesData () {
502 return CustomAttributeData.GetCustomAttributes (this);
506 static int get_core_clr_security_level ()
511 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
512 [MethodImplAttribute(MethodImplOptions.InternalCall)]
513 public extern int get_core_clr_security_level ();
516 public override bool IsSecurityTransparent {
517 get { return get_core_clr_security_level () == 0; }
520 public override bool IsSecurityCritical {
521 get { return get_core_clr_security_level () > 0; }
524 public override bool IsSecuritySafeCritical {
525 get { return get_core_clr_security_level () == 1; }
530 abstract class RuntimeConstructorInfo : ConstructorInfo, ISerializable
532 public override Module Module {
534 return GetRuntimeModule ();
538 internal RuntimeModule GetRuntimeModule ()
540 return RuntimeTypeHandle.GetModule((RuntimeType)DeclaringType);
543 internal BindingFlags BindingFlags {
549 RuntimeType ReflectedTypeInternal {
551 return (RuntimeType) ReflectedType;
555 #region ISerializable Implementation
556 public void GetObjectData(SerializationInfo info, StreamingContext context)
559 throw new ArgumentNullException("info");
560 Contract.EndContractBlock();
561 MemberInfoSerializationHolder.GetSerializationInfo(
564 ReflectedTypeInternal,
566 SerializationToString(),
567 MemberTypes.Constructor,
571 internal string SerializationToString()
573 // We don't need the return type for constructors.
574 return FormatNameAndSig(true);
577 internal void SerializationInvoke (Object target, SerializationInfo info, StreamingContext context)
579 Invoke (target, new object[] { info, context });
585 [StructLayout (LayoutKind.Sequential)]
586 internal class MonoCMethod : RuntimeConstructorInfo
588 #pragma warning disable 649
589 internal IntPtr mhandle;
592 #pragma warning restore 649
594 public override MethodImplAttributes GetMethodImplementationFlags ()
596 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
599 public override ParameterInfo[] GetParameters ()
601 return MonoMethodInfo.GetParametersInfo (mhandle, this);
604 internal override ParameterInfo[] GetParametersInternal ()
606 return MonoMethodInfo.GetParametersInfo (mhandle, this);
609 internal override int GetParametersCount ()
611 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
612 return pi == null ? 0 : pi.Length;
616 * InternalInvoke() receives the parameters correctly converted by the binder
617 * to match the types of the method signature.
619 [MethodImplAttribute(MethodImplOptions.InternalCall)]
620 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
623 [DebuggerStepThrough]
624 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
628 throw new TargetException ("Instance constructor requires a target");
629 } else if (!DeclaringType.IsInstanceOfType (obj)) {
630 throw new TargetException ("Constructor does not match target type");
633 return DoInvoke (obj, invokeAttr, binder, parameters, culture);
636 object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
639 binder = Type.DefaultBinder;
641 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
643 MonoMethod.ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
645 if (obj == null && DeclaringType.ContainsGenericParameters)
646 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
648 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
649 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
652 return InternalInvoke (obj, parameters);
655 public object InternalInvoke (object obj, object[] parameters)
661 o = InternalInvoke (obj, parameters, out exc);
663 } catch (MethodAccessException) {
666 } catch (Exception e) {
667 throw new TargetInvocationException (e);
673 return obj == null ? o : null;
677 [DebuggerStepThrough]
678 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
680 return DoInvoke (null, invokeAttr, binder, parameters, culture);
683 public override RuntimeMethodHandle MethodHandle {
685 return new RuntimeMethodHandle (mhandle);
689 public override MethodAttributes Attributes {
691 return MonoMethodInfo.GetAttributes (mhandle);
695 public override CallingConventions CallingConvention {
697 return MonoMethodInfo.GetCallingConvention (mhandle);
701 public override bool ContainsGenericParameters {
703 return DeclaringType.ContainsGenericParameters;
707 public override Type ReflectedType {
712 public override Type DeclaringType {
714 return MonoMethodInfo.GetDeclaringType (mhandle);
717 public override string Name {
721 return MonoMethod.get_name (this);
725 public override bool IsDefined (Type attributeType, bool inherit) {
726 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
729 public override object[] GetCustomAttributes( bool inherit) {
730 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
733 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
734 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
737 public override MethodBody GetMethodBody () {
738 return GetMethodBody (mhandle);
741 public override string ToString () {
742 StringBuilder sb = new StringBuilder ();
746 ParameterInfo[] p = GetParameters ();
747 for (int i = 0; i < p.Length; ++i) {
750 sb.Append (p[i].ParameterType.Name);
752 if (CallingConvention == CallingConventions.Any)
755 return sb.ToString ();
758 public override IList<CustomAttributeData> GetCustomAttributesData () {
759 return CustomAttributeData.GetCustomAttributes (this);
763 static int get_core_clr_security_level ()
768 [MethodImplAttribute(MethodImplOptions.InternalCall)]
769 public extern int get_core_clr_security_level ();
772 public override bool IsSecurityTransparent {
773 get { return get_core_clr_security_level () == 0; }
776 public override bool IsSecurityCritical {
777 get { return get_core_clr_security_level () > 0; }
780 public override bool IsSecuritySafeCritical {
781 get { return get_core_clr_security_level () == 1; }