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;
37 using System.Reflection.Emit;
38 using System.Security;
39 using System.Threading;
41 using System.Diagnostics;
43 namespace System.Reflection {
45 internal struct MonoMethodInfo
47 #pragma warning disable 649
50 internal MethodAttributes attrs;
51 internal MethodImplAttributes iattrs;
52 private CallingConventions callconv;
53 #pragma warning restore 649
55 [MethodImplAttribute(MethodImplOptions.InternalCall)]
56 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
58 [MethodImplAttribute(MethodImplOptions.InternalCall)]
59 static extern int get_method_attributes (IntPtr handle);
61 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
64 MonoMethodInfo.get_method_info (handle, out info);
68 internal static Type GetDeclaringType (IntPtr handle)
70 return GetMethodInfo (handle).parent;
73 internal static Type GetReturnType (IntPtr handle)
75 return GetMethodInfo (handle).ret;
78 internal static MethodAttributes GetAttributes (IntPtr handle)
80 return (MethodAttributes)get_method_attributes (handle);
83 internal static CallingConventions GetCallingConvention (IntPtr handle)
85 return GetMethodInfo (handle).callconv;
88 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
90 return GetMethodInfo (handle).iattrs;
93 [MethodImplAttribute(MethodImplOptions.InternalCall)]
94 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
96 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
98 return get_parameter_info (handle, member);
101 [MethodImplAttribute(MethodImplOptions.InternalCall)]
102 static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
104 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
106 return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
111 * Note: most of this class needs to be duplicated for the contructor, since
112 * the .NET reflection class hierarchy is so broken.
115 [StructLayout (LayoutKind.Sequential)]
116 internal class MonoMethod : MethodInfo, ISerializable
118 #pragma warning disable 649
119 internal IntPtr mhandle;
122 #pragma warning restore 649
124 internal MonoMethod () {
127 internal MonoMethod (RuntimeMethodHandle mhandle) {
128 this.mhandle = mhandle.Value;
131 [MethodImplAttribute(MethodImplOptions.InternalCall)]
132 internal static extern string get_name (MethodBase method);
134 [MethodImplAttribute(MethodImplOptions.InternalCall)]
135 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
137 public override MethodInfo GetBaseDefinition ()
139 return get_base_method (this, true);
142 internal override MethodInfo GetBaseMethod ()
144 return get_base_method (this, false);
147 public override ParameterInfo ReturnParameter {
149 return MonoMethodInfo.GetReturnParameterInfo (this);
153 public override Type ReturnType {
155 return MonoMethodInfo.GetReturnType (mhandle);
158 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
160 return MonoMethodInfo.GetReturnParameterInfo (this);
164 public override MethodImplAttributes GetMethodImplementationFlags ()
166 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
169 public override ParameterInfo[] GetParameters ()
171 ParameterInfo[] src = MonoMethodInfo.GetParametersInfo (mhandle, this);
172 ParameterInfo[] res = new ParameterInfo [src.Length];
177 internal override int GetParameterCount ()
179 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
180 return pi == null ? 0 : pi.Length;
184 * InternalInvoke() receives the parameters correctly converted by the
185 * binder to match the types of the method signature.
187 [MethodImplAttribute(MethodImplOptions.InternalCall)]
188 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
191 [DebuggerStepThrough]
192 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
195 binder = Binder.DefaultBinder;
197 /*Avoid allocating an array every time*/
198 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
199 if (!binder.ConvertArgs (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0))
200 throw new ArgumentException ("failed to convert parameters");
203 if (SecurityManager.SecurityEnabled) {
204 // sadly Attributes doesn't tell us which kind of security action this is so
205 // we must do it the hard way - and it also means that we can skip calling
206 // Attribute (which is another an icall)
207 SecurityManager.ReflectedLinkDemandInvoke (this);
211 if (ContainsGenericParameters)
212 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
218 // The ex argument is used to distinguish exceptions thrown by the icall
219 // from the exceptions thrown by the called method (which need to be
220 // wrapped in TargetInvocationException).
221 o = InternalInvoke (obj, parameters, out exc);
222 } catch (ThreadAbortException) {
225 } catch (MethodAccessException) {
228 } catch (Exception e) {
229 throw new TargetInvocationException (e);
237 public override RuntimeMethodHandle MethodHandle {
239 return new RuntimeMethodHandle (mhandle);
243 public override MethodAttributes Attributes {
245 return MonoMethodInfo.GetAttributes (mhandle);
249 public override CallingConventions CallingConvention {
251 return MonoMethodInfo.GetCallingConvention (mhandle);
255 public override Type ReflectedType {
260 public override Type DeclaringType {
262 return MonoMethodInfo.GetDeclaringType (mhandle);
265 public override string Name {
269 return get_name (this);
273 public override bool IsDefined (Type attributeType, bool inherit) {
274 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
277 public override object[] GetCustomAttributes( bool inherit) {
278 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
280 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
281 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
284 [MethodImplAttribute(MethodImplOptions.InternalCall)]
285 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
287 internal object[] GetPseudoCustomAttributes ()
291 /* MS.NET doesn't report MethodImplAttribute */
293 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
294 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
296 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
301 object[] attrs = new object [count];
304 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
305 attrs [count ++] = new PreserveSigAttribute ();
306 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
307 DllImportAttribute attr = GetDllImportAttribute (mhandle);
308 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
309 attr.PreserveSig = true;
310 attrs [count ++] = attr;
316 static bool ShouldPrintFullName (Type type) {
317 return type.IsClass && (!type.IsPointer ||
318 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
321 public override string ToString () {
322 StringBuilder sb = new StringBuilder ();
323 Type retType = ReturnType;
324 if (ShouldPrintFullName (retType))
325 sb.Append (retType.ToString ());
327 sb.Append (retType.Name);
330 if (IsGenericMethod) {
331 Type[] gen_params = GetGenericArguments ();
333 for (int j = 0; j < gen_params.Length; j++) {
336 sb.Append (gen_params [j].Name);
341 ParameterInfo[] p = GetParameters ();
342 for (int i = 0; i < p.Length; ++i) {
345 Type pt = p[i].ParameterType;
346 bool byref = pt.IsByRef;
348 pt = pt.GetElementType ();
349 if (ShouldPrintFullName (pt))
350 sb.Append (pt.ToString ());
354 sb.Append (" ByRef");
356 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
363 return sb.ToString ();
368 public void GetObjectData(SerializationInfo info, StreamingContext context)
370 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
371 ? GetGenericArguments () : null;
372 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
375 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
377 if (methodInstantiation == null)
378 throw new ArgumentNullException ("methodInstantiation");
380 if (!IsGenericMethodDefinition)
381 throw new InvalidOperationException ("not a generic method definition");
383 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
384 if (GetGenericArguments ().Length != methodInstantiation.Length)
385 throw new ArgumentException ("Incorrect length");
387 bool hasUserType = false;
388 foreach (Type type in methodInstantiation) {
390 throw new ArgumentNullException ();
391 if (!(type is MonoType))
396 return new MethodOnTypeBuilderInst (this, methodInstantiation);
398 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
400 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
404 [MethodImplAttribute(MethodImplOptions.InternalCall)]
405 extern MethodInfo MakeGenericMethod_impl (Type [] types);
407 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408 public override extern Type [] GetGenericArguments ();
410 [MethodImplAttribute(MethodImplOptions.InternalCall)]
411 extern MethodInfo GetGenericMethodDefinition_impl ();
413 public override MethodInfo GetGenericMethodDefinition ()
415 MethodInfo res = GetGenericMethodDefinition_impl ();
417 throw new InvalidOperationException ();
422 public override extern bool IsGenericMethodDefinition {
423 [MethodImplAttribute(MethodImplOptions.InternalCall)]
427 public override extern bool IsGenericMethod {
428 [MethodImplAttribute(MethodImplOptions.InternalCall)]
432 public override bool ContainsGenericParameters {
434 if (IsGenericMethod) {
435 foreach (Type arg in GetGenericArguments ())
436 if (arg.ContainsGenericParameters)
439 return DeclaringType.ContainsGenericParameters;
443 public override MethodBody GetMethodBody () {
444 return GetMethodBody (mhandle);
448 public override IList<CustomAttributeData> GetCustomAttributesData () {
449 return CustomAttributeData.GetCustomAttributes (this);
454 [StructLayout (LayoutKind.Sequential)]
455 internal class MonoCMethod : ConstructorInfo, ISerializable
457 #pragma warning disable 649
458 internal IntPtr mhandle;
461 #pragma warning restore 649
463 public override MethodImplAttributes GetMethodImplementationFlags ()
465 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
468 public override ParameterInfo[] GetParameters ()
470 return MonoMethodInfo.GetParametersInfo (mhandle, this);
473 internal override int GetParameterCount ()
475 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
476 return pi == null ? 0 : pi.Length;
480 * InternalInvoke() receives the parameters corretcly converted by the binder
481 * to match the types of the method signature.
483 [MethodImplAttribute(MethodImplOptions.InternalCall)]
484 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
487 [DebuggerStepThrough]
488 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
491 binder = Binder.DefaultBinder;
493 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
495 if (!binder.ConvertArgs (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0))
496 throw new ArgumentException ("failed to convert parameters");
499 if (SecurityManager.SecurityEnabled) {
500 // sadly Attributes doesn't tell us which kind of security action this is so
501 // we must do it the hard way - and it also means that we can skip calling
502 // Attribute (which is another an icall)
503 SecurityManager.ReflectedLinkDemandInvoke (this);
507 if (obj == null && DeclaringType.ContainsGenericParameters)
508 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
510 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
511 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
514 Exception exc = null;
518 o = InternalInvoke (obj, parameters, out exc);
520 } catch (MethodAccessException) {
523 } catch (Exception e) {
524 throw new TargetInvocationException (e);
529 return (obj == null) ? o : null;
533 [DebuggerStepThrough]
534 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
536 return Invoke (null, invokeAttr, binder, parameters, culture);
539 public override RuntimeMethodHandle MethodHandle {
541 return new RuntimeMethodHandle (mhandle);
545 public override MethodAttributes Attributes {
547 return MonoMethodInfo.GetAttributes (mhandle);
551 public override CallingConventions CallingConvention {
553 return MonoMethodInfo.GetCallingConvention (mhandle);
557 public override Type ReflectedType {
562 public override Type DeclaringType {
564 return MonoMethodInfo.GetDeclaringType (mhandle);
567 public override string Name {
571 return MonoMethod.get_name (this);
575 public override bool IsDefined (Type attributeType, bool inherit) {
576 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
579 public override object[] GetCustomAttributes( bool inherit) {
580 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
583 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
584 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
587 public override MethodBody GetMethodBody () {
588 return GetMethodBody (mhandle);
591 public override string ToString () {
592 StringBuilder sb = new StringBuilder ();
596 ParameterInfo[] p = GetParameters ();
597 for (int i = 0; i < p.Length; ++i) {
600 sb.Append (p[i].ParameterType.Name);
602 if (CallingConvention == CallingConventions.Any)
605 return sb.ToString ();
609 public void GetObjectData(SerializationInfo info, StreamingContext context)
611 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
615 public override IList<CustomAttributeData> GetCustomAttributesData () {
616 return CustomAttributeData.GetCustomAttributes (this);