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;
40 using System.Diagnostics;
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 [StructLayout (LayoutKind.Sequential)]
115 internal class MonoMethod : MethodInfo, ISerializable
117 #pragma warning disable 649
118 internal IntPtr mhandle;
121 #pragma warning restore 649
123 internal MonoMethod () {
126 internal MonoMethod (RuntimeMethodHandle mhandle) {
127 this.mhandle = mhandle.Value;
130 [MethodImplAttribute(MethodImplOptions.InternalCall)]
131 internal static extern string get_name (MethodBase method);
133 [MethodImplAttribute(MethodImplOptions.InternalCall)]
134 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
136 public override MethodInfo GetBaseDefinition ()
138 return get_base_method (this, true);
141 internal override MethodInfo GetBaseMethod ()
143 return get_base_method (this, false);
146 public override ParameterInfo ReturnParameter {
148 return MonoMethodInfo.GetReturnParameterInfo (this);
152 public override Type ReturnType {
154 return MonoMethodInfo.GetReturnType (mhandle);
157 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
159 return MonoMethodInfo.GetReturnParameterInfo (this);
163 public override MethodImplAttributes GetMethodImplementationFlags ()
165 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
168 public override ParameterInfo[] GetParameters ()
170 ParameterInfo[] src = MonoMethodInfo.GetParametersInfo (mhandle, this);
171 ParameterInfo[] res = new ParameterInfo [src.Length];
176 internal override int GetParameterCount ()
178 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
179 return pi == null ? 0 : pi.Length;
183 * InternalInvoke() receives the parameters correctly converted by the
184 * binder to match the types of the method signature.
186 [MethodImplAttribute(MethodImplOptions.InternalCall)]
187 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
190 [DebuggerStepThrough]
191 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
194 binder = Binder.DefaultBinder;
195 /*Avoid allocating an array every time*/
196 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
198 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
199 throw new TargetParameterCountException ("parameters do not match signature");
201 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
202 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
203 throw new ArgumentException ("failed to convert parameters");
205 for (int i = 0; i < pinfo.Length; i++)
206 if (parameters[i].GetType() != pinfo[i].ParameterType)
207 throw new ArgumentException ("parameters do not match signature");
211 if (SecurityManager.SecurityEnabled) {
212 // sadly Attributes doesn't tell us which kind of security action this is so
213 // we must do it the hard way - and it also means that we can skip calling
214 // Attribute (which is another an icall)
215 SecurityManager.ReflectedLinkDemandInvoke (this);
219 if (ContainsGenericParameters)
220 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
226 // The ex argument is used to distinguish exceptions thrown by the icall
227 // from the exceptions thrown by the called method (which need to be
228 // wrapped in TargetInvocationException).
229 o = InternalInvoke (obj, parameters, out exc);
230 } catch (ThreadAbortException) {
233 } catch (MethodAccessException) {
236 } catch (Exception e) {
237 throw new TargetInvocationException (e);
245 public override RuntimeMethodHandle MethodHandle {
247 return new RuntimeMethodHandle (mhandle);
251 public override MethodAttributes Attributes {
253 return MonoMethodInfo.GetAttributes (mhandle);
257 public override CallingConventions CallingConvention {
259 return MonoMethodInfo.GetCallingConvention (mhandle);
263 public override Type ReflectedType {
268 public override Type DeclaringType {
270 return MonoMethodInfo.GetDeclaringType (mhandle);
273 public override string Name {
277 return get_name (this);
281 public override bool IsDefined (Type attributeType, bool inherit) {
282 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
285 public override object[] GetCustomAttributes( bool inherit) {
286 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
288 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
289 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
292 [MethodImplAttribute(MethodImplOptions.InternalCall)]
293 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
295 internal object[] GetPseudoCustomAttributes ()
299 /* MS.NET doesn't report MethodImplAttribute */
301 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
302 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
304 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
309 object[] attrs = new object [count];
312 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
313 attrs [count ++] = new PreserveSigAttribute ();
314 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
315 DllImportAttribute attr = GetDllImportAttribute (mhandle);
316 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
317 attr.PreserveSig = true;
318 attrs [count ++] = attr;
324 static bool ShouldPrintFullName (Type type) {
325 return type.IsClass && (!type.IsPointer ||
326 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
329 public override string ToString () {
330 StringBuilder sb = new StringBuilder ();
331 Type retType = ReturnType;
332 if (ShouldPrintFullName (retType))
333 sb.Append (retType.ToString ());
335 sb.Append (retType.Name);
338 if (IsGenericMethod) {
339 Type[] gen_params = GetGenericArguments ();
341 for (int j = 0; j < gen_params.Length; j++) {
344 sb.Append (gen_params [j].Name);
349 ParameterInfo[] p = GetParameters ();
350 for (int i = 0; i < p.Length; ++i) {
353 Type pt = p[i].ParameterType;
354 bool byref = pt.IsByRef;
356 pt = pt.GetElementType ();
357 if (ShouldPrintFullName (pt))
358 sb.Append (pt.ToString ());
362 sb.Append (" ByRef");
364 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
371 return sb.ToString ();
376 public void GetObjectData(SerializationInfo info, StreamingContext context)
378 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
379 ? GetGenericArguments () : null;
380 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
383 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
385 if (methodInstantiation == null)
386 throw new ArgumentNullException ("methodInstantiation");
388 if (!IsGenericMethodDefinition)
389 throw new InvalidOperationException ("not a generic method definition");
391 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
392 if (GetGenericArguments ().Length != methodInstantiation.Length)
393 throw new ArgumentException ("Incorrect length");
395 bool hasUserType = false;
396 foreach (Type type in methodInstantiation) {
398 throw new ArgumentNullException ();
399 if (!(type is MonoType))
404 return new MethodOnTypeBuilderInst (this, methodInstantiation);
406 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
408 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
412 [MethodImplAttribute(MethodImplOptions.InternalCall)]
413 extern MethodInfo MakeGenericMethod_impl (Type [] types);
415 [MethodImplAttribute(MethodImplOptions.InternalCall)]
416 public override extern Type [] GetGenericArguments ();
418 [MethodImplAttribute(MethodImplOptions.InternalCall)]
419 extern MethodInfo GetGenericMethodDefinition_impl ();
421 public override MethodInfo GetGenericMethodDefinition ()
423 MethodInfo res = GetGenericMethodDefinition_impl ();
425 throw new InvalidOperationException ();
430 public override extern bool IsGenericMethodDefinition {
431 [MethodImplAttribute(MethodImplOptions.InternalCall)]
435 public override extern bool IsGenericMethod {
436 [MethodImplAttribute(MethodImplOptions.InternalCall)]
440 public override bool ContainsGenericParameters {
442 if (IsGenericMethod) {
443 foreach (Type arg in GetGenericArguments ())
444 if (arg.ContainsGenericParameters)
447 return DeclaringType.ContainsGenericParameters;
451 public override MethodBody GetMethodBody () {
452 return GetMethodBody (mhandle);
456 public override IList<CustomAttributeData> GetCustomAttributesData () {
457 return CustomAttributeData.GetCustomAttributes (this);
462 [StructLayout (LayoutKind.Sequential)]
463 internal class MonoCMethod : ConstructorInfo, ISerializable
465 #pragma warning disable 649
466 internal IntPtr mhandle;
469 #pragma warning restore 649
471 public override MethodImplAttributes GetMethodImplementationFlags ()
473 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
476 public override ParameterInfo[] GetParameters ()
478 return MonoMethodInfo.GetParametersInfo (mhandle, this);
481 internal override int GetParameterCount ()
483 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
484 return pi == null ? 0 : pi.Length;
488 * InternalInvoke() receives the parameters corretcly converted by the binder
489 * to match the types of the method signature.
491 [MethodImplAttribute(MethodImplOptions.InternalCall)]
492 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
495 [DebuggerStepThrough]
496 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
499 binder = Binder.DefaultBinder;
501 ParameterInfo[] pinfo = GetParameters ();
503 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
504 throw new TargetParameterCountException ("parameters do not match signature");
506 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
507 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
508 throw new ArgumentException ("failed to convert parameters");
510 for (int i = 0; i < pinfo.Length; i++)
511 if (parameters[i].GetType() != pinfo[i].ParameterType)
512 throw new ArgumentException ("parameters do not match signature");
516 if (SecurityManager.SecurityEnabled) {
517 // sadly Attributes doesn't tell us which kind of security action this is so
518 // we must do it the hard way - and it also means that we can skip calling
519 // Attribute (which is another an icall)
520 SecurityManager.ReflectedLinkDemandInvoke (this);
524 if (obj == null && DeclaringType.ContainsGenericParameters)
525 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
527 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
528 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
531 Exception exc = null;
535 o = InternalInvoke (obj, parameters, out exc);
537 } catch (MethodAccessException) {
540 } catch (Exception e) {
541 throw new TargetInvocationException (e);
546 return (obj == null) ? o : null;
550 [DebuggerStepThrough]
551 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
553 return Invoke (null, invokeAttr, binder, parameters, culture);
556 public override RuntimeMethodHandle MethodHandle {
558 return new RuntimeMethodHandle (mhandle);
562 public override MethodAttributes Attributes {
564 return MonoMethodInfo.GetAttributes (mhandle);
568 public override CallingConventions CallingConvention {
570 return MonoMethodInfo.GetCallingConvention (mhandle);
574 public override Type ReflectedType {
579 public override Type DeclaringType {
581 return MonoMethodInfo.GetDeclaringType (mhandle);
584 public override string Name {
588 return MonoMethod.get_name (this);
592 public override bool IsDefined (Type attributeType, bool inherit) {
593 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
596 public override object[] GetCustomAttributes( bool inherit) {
597 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
600 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
601 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
604 public override MethodBody GetMethodBody () {
605 return GetMethodBody (mhandle);
608 public override string ToString () {
609 StringBuilder sb = new StringBuilder ();
613 ParameterInfo[] p = GetParameters ();
614 for (int i = 0; i < p.Length; ++i) {
617 sb.Append (p[i].ParameterType.Name);
619 if (CallingConvention == CallingConventions.Any)
622 return sb.ToString ();
626 public void GetObjectData(SerializationInfo info, StreamingContext context)
628 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
632 public override IList<CustomAttributeData> GetCustomAttributesData () {
633 return CustomAttributeData.GetCustomAttributes (this);