2 // System.Reflection/MonoMethod.cs
3 // The class used to represent methods from the mono runtime.
6 // Paolo Molaro (lupus@ximian.com)
8 // (C) 2001 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections.Generic;
32 using System.Globalization;
33 using System.Runtime.CompilerServices;
34 using System.Runtime.InteropServices;
35 using System.Runtime.Serialization;
36 using System.Reflection.Emit;
37 using System.Security;
38 using System.Threading;
42 namespace System.Reflection {
44 internal struct MonoMethodInfo
46 #pragma warning disable 649
49 internal MethodAttributes attrs;
50 internal MethodImplAttributes iattrs;
51 private CallingConventions callconv;
52 #pragma warning restore 649
54 [MethodImplAttribute(MethodImplOptions.InternalCall)]
55 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
57 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58 static extern int get_method_attributes (IntPtr handle);
60 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
63 MonoMethodInfo.get_method_info (handle, out info);
67 internal static Type GetDeclaringType (IntPtr handle)
69 return GetMethodInfo (handle).parent;
72 internal static Type GetReturnType (IntPtr handle)
74 return GetMethodInfo (handle).ret;
77 internal static MethodAttributes GetAttributes (IntPtr handle)
79 return (MethodAttributes)get_method_attributes (handle);
82 internal static CallingConventions GetCallingConvention (IntPtr handle)
84 return GetMethodInfo (handle).callconv;
87 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
89 return GetMethodInfo (handle).iattrs;
92 [MethodImplAttribute(MethodImplOptions.InternalCall)]
93 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
95 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
97 return get_parameter_info (handle, member);
100 [MethodImplAttribute(MethodImplOptions.InternalCall)]
101 static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
103 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
105 return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
110 * Note: most of this class needs to be duplicated for the contructor, since
111 * the .NET reflection class hierarchy is so broken.
114 internal class MonoMethod : MethodInfo, ISerializable
116 #pragma warning disable 649
117 internal IntPtr mhandle;
120 #pragma warning restore 649
122 internal MonoMethod () {
125 internal MonoMethod (RuntimeMethodHandle mhandle) {
126 this.mhandle = mhandle.Value;
129 [MethodImplAttribute(MethodImplOptions.InternalCall)]
130 internal static extern string get_name (MethodBase method);
132 [MethodImplAttribute(MethodImplOptions.InternalCall)]
133 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
135 public override MethodInfo GetBaseDefinition ()
137 return get_base_method (this, true);
140 internal override MethodInfo GetBaseMethod ()
142 return get_base_method (this, false);
145 public override ParameterInfo ReturnParameter {
147 return MonoMethodInfo.GetReturnParameterInfo (this);
151 public override Type ReturnType {
153 return MonoMethodInfo.GetReturnType (mhandle);
156 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
158 return MonoMethodInfo.GetReturnParameterInfo (this);
162 public override MethodImplAttributes GetMethodImplementationFlags ()
164 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
167 public override ParameterInfo[] GetParameters ()
169 ParameterInfo[] src = MonoMethodInfo.GetParametersInfo (mhandle, this);
170 ParameterInfo[] res = new ParameterInfo [src.Length];
175 internal override int GetParameterCount ()
177 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
178 return pi == null ? 0 : pi.Length;
182 * InternalInvoke() receives the parameters correctly converted by the
183 * binder to match the types of the method signature.
185 [MethodImplAttribute(MethodImplOptions.InternalCall)]
186 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
188 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
191 binder = Binder.DefaultBinder;
192 /*Avoid allocating an array every time*/
193 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
195 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
196 throw new TargetParameterCountException ("parameters do not match signature");
198 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
199 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
200 throw new ArgumentException ("failed to convert parameters");
202 for (int i = 0; i < pinfo.Length; i++)
203 if (parameters[i].GetType() != pinfo[i].ParameterType)
204 throw new ArgumentException ("parameters do not match signature");
208 if (SecurityManager.SecurityEnabled) {
209 // sadly Attributes doesn't tell us which kind of security action this is so
210 // we must do it the hard way - and it also means that we can skip calling
211 // Attribute (which is another an icall)
212 SecurityManager.ReflectedLinkDemandInvoke (this);
216 if (ContainsGenericParameters)
217 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
223 // The ex argument is used to distinguish exceptions thrown by the icall
224 // from the exceptions thrown by the called method (which need to be
225 // wrapped in TargetInvocationException).
226 o = InternalInvoke (obj, parameters, out exc);
227 } catch (ThreadAbortException) {
230 } catch (MethodAccessException) {
233 } catch (Exception e) {
234 throw new TargetInvocationException (e);
242 public override RuntimeMethodHandle MethodHandle {
243 get {return new RuntimeMethodHandle (mhandle);}
245 public override MethodAttributes Attributes {
247 return MonoMethodInfo.GetAttributes (mhandle);
251 public override CallingConventions CallingConvention {
253 return MonoMethodInfo.GetCallingConvention (mhandle);
257 public override Type ReflectedType {
262 public override Type DeclaringType {
264 return MonoMethodInfo.GetDeclaringType (mhandle);
267 public override string Name {
271 return get_name (this);
275 public override bool IsDefined (Type attributeType, bool inherit) {
276 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
279 public override object[] GetCustomAttributes( bool inherit) {
280 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
282 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
283 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
286 [MethodImplAttribute(MethodImplOptions.InternalCall)]
287 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
289 internal object[] GetPseudoCustomAttributes ()
293 /* MS.NET doesn't report MethodImplAttribute */
295 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
296 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
298 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
303 object[] attrs = new object [count];
306 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
307 attrs [count ++] = new PreserveSigAttribute ();
308 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
309 DllImportAttribute attr = GetDllImportAttribute (mhandle);
310 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
311 attr.PreserveSig = true;
312 attrs [count ++] = attr;
318 static bool ShouldPrintFullName (Type type) {
319 return type.IsClass && (!type.IsPointer ||
320 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
323 public override string ToString () {
324 StringBuilder sb = new StringBuilder ();
325 Type retType = ReturnType;
326 if (ShouldPrintFullName (retType))
327 sb.Append (retType.ToString ());
329 sb.Append (retType.Name);
332 if (IsGenericMethod) {
333 Type[] gen_params = GetGenericArguments ();
335 for (int j = 0; j < gen_params.Length; j++) {
338 sb.Append (gen_params [j].Name);
343 ParameterInfo[] p = GetParameters ();
344 for (int i = 0; i < p.Length; ++i) {
347 Type pt = p[i].ParameterType;
348 bool byref = pt.IsByRef;
350 pt = pt.GetElementType ();
351 if (ShouldPrintFullName (pt))
352 sb.Append (pt.ToString ());
356 sb.Append (" ByRef");
358 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
365 return sb.ToString ();
370 public void GetObjectData(SerializationInfo info, StreamingContext context)
372 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
373 ? GetGenericArguments () : null;
374 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
377 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
379 if (methodInstantiation == null)
380 throw new ArgumentNullException ("methodInstantiation");
382 if (!IsGenericMethodDefinition)
383 throw new InvalidOperationException ("not a generic method definition");
385 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
386 if (GetGenericArguments ().Length != methodInstantiation.Length)
387 throw new ArgumentException ("Incorrect length");
389 bool hasUserType = false;
390 foreach (Type type in methodInstantiation) {
392 throw new ArgumentNullException ();
393 if (!(type is MonoType))
398 return new MethodOnTypeBuilderInst (this, methodInstantiation);
400 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
402 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
406 [MethodImplAttribute(MethodImplOptions.InternalCall)]
407 extern MethodInfo MakeGenericMethod_impl (Type [] types);
409 [MethodImplAttribute(MethodImplOptions.InternalCall)]
410 public override extern Type [] GetGenericArguments ();
412 [MethodImplAttribute(MethodImplOptions.InternalCall)]
413 extern MethodInfo GetGenericMethodDefinition_impl ();
415 public override MethodInfo GetGenericMethodDefinition ()
417 MethodInfo res = GetGenericMethodDefinition_impl ();
419 throw new InvalidOperationException ();
424 public override extern bool IsGenericMethodDefinition {
425 [MethodImplAttribute(MethodImplOptions.InternalCall)]
429 public override extern bool IsGenericMethod {
430 [MethodImplAttribute(MethodImplOptions.InternalCall)]
434 public override bool ContainsGenericParameters {
436 if (IsGenericMethod) {
437 foreach (Type arg in GetGenericArguments ())
438 if (arg.ContainsGenericParameters)
441 return DeclaringType.ContainsGenericParameters;
445 public override MethodBody GetMethodBody () {
446 return GetMethodBody (mhandle);
450 public override IList<CustomAttributeData> GetCustomAttributesData () {
451 return CustomAttributeData.GetCustomAttributes (this);
456 internal class MonoCMethod : ConstructorInfo, ISerializable
458 #pragma warning disable 649
459 internal IntPtr mhandle;
462 #pragma warning restore 649
464 public override MethodImplAttributes GetMethodImplementationFlags ()
466 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
469 public override ParameterInfo[] GetParameters ()
471 return MonoMethodInfo.GetParametersInfo (mhandle, this);
474 internal override int GetParameterCount ()
476 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
477 return pi == null ? 0 : pi.Length;
481 * InternalInvoke() receives the parameters corretcly converted by the binder
482 * to match the types of the method signature.
484 [MethodImplAttribute(MethodImplOptions.InternalCall)]
485 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
487 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
490 binder = Binder.DefaultBinder;
492 ParameterInfo[] pinfo = GetParameters ();
494 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
495 throw new TargetParameterCountException ("parameters do not match signature");
497 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
498 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
499 throw new ArgumentException ("failed to convert parameters");
501 for (int i = 0; i < pinfo.Length; i++)
502 if (parameters[i].GetType() != pinfo[i].ParameterType)
503 throw new ArgumentException ("parameters do not match signature");
507 if (SecurityManager.SecurityEnabled) {
508 // sadly Attributes doesn't tell us which kind of security action this is so
509 // we must do it the hard way - and it also means that we can skip calling
510 // Attribute (which is another an icall)
511 SecurityManager.ReflectedLinkDemandInvoke (this);
515 if (obj == null && DeclaringType.ContainsGenericParameters)
516 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
518 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
519 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
522 Exception exc = null;
526 o = InternalInvoke (obj, parameters, out exc);
528 } catch (MethodAccessException) {
531 } catch (Exception e) {
532 throw new TargetInvocationException (e);
537 return (obj == null) ? o : null;
540 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
541 return Invoke (null, invokeAttr, binder, parameters, culture);
544 public override RuntimeMethodHandle MethodHandle {
545 get {return new RuntimeMethodHandle (mhandle);}
547 public override MethodAttributes Attributes {
549 return MonoMethodInfo.GetAttributes (mhandle);
553 public override CallingConventions CallingConvention {
555 return MonoMethodInfo.GetCallingConvention (mhandle);
559 public override Type ReflectedType {
564 public override Type DeclaringType {
566 return MonoMethodInfo.GetDeclaringType (mhandle);
569 public override string Name {
573 return MonoMethod.get_name (this);
577 public override bool IsDefined (Type attributeType, bool inherit) {
578 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
581 public override object[] GetCustomAttributes( bool inherit) {
582 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
585 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
586 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
589 public override MethodBody GetMethodBody () {
590 return GetMethodBody (mhandle);
593 public override string ToString () {
594 StringBuilder sb = new StringBuilder ();
598 ParameterInfo[] p = GetParameters ();
599 for (int i = 0; i < p.Length; ++i) {
602 sb.Append (p[i].ParameterType.Name);
604 if (CallingConvention == CallingConventions.Any)
607 return sb.ToString ();
611 public void GetObjectData(SerializationInfo info, StreamingContext context)
613 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
617 public override IList<CustomAttributeData> GetCustomAttributesData () {
618 return CustomAttributeData.GetCustomAttributes (this);