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.Globalization;
32 using System.Runtime.CompilerServices;
33 using System.Runtime.InteropServices;
34 using System.Runtime.Serialization;
35 using System.Reflection.Emit;
36 using System.Security;
37 using System.Threading;
41 namespace System.Reflection {
43 internal struct MonoMethodInfo
47 internal MethodAttributes attrs;
48 internal MethodImplAttributes iattrs;
49 private CallingConventions callconv;
51 [MethodImplAttribute(MethodImplOptions.InternalCall)]
52 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
54 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
57 MonoMethodInfo.get_method_info (handle, out info);
61 internal static Type GetDeclaringType (IntPtr handle)
63 return GetMethodInfo (handle).parent;
66 internal static Type GetReturnType (IntPtr handle)
68 return GetMethodInfo (handle).ret;
71 internal static MethodAttributes GetAttributes (IntPtr handle)
73 return GetMethodInfo (handle).attrs;
76 internal static CallingConventions GetCallingConvention (IntPtr handle)
78 return GetMethodInfo (handle).callconv;
81 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
83 return GetMethodInfo (handle).iattrs;
86 [MethodImplAttribute(MethodImplOptions.InternalCall)]
87 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
89 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
91 return get_parameter_info (handle, member);
94 [MethodImplAttribute(MethodImplOptions.InternalCall)]
95 static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
97 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
99 return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
104 * Note: most of this class needs to be duplicated for the contructor, since
105 * the .NET reflection class hierarchy is so broken.
108 internal class MonoMethod : MethodInfo, ISerializable
110 #pragma warning disable 649
111 internal IntPtr mhandle;
114 #pragma warning restore 649
116 internal MonoMethod () {
119 internal MonoMethod (RuntimeMethodHandle mhandle) {
120 this.mhandle = mhandle.Value;
123 [MethodImplAttribute(MethodImplOptions.InternalCall)]
124 internal static extern string get_name (MethodBase method);
126 [MethodImplAttribute(MethodImplOptions.InternalCall)]
127 internal static extern MonoMethod get_base_definition (MonoMethod method);
129 public override MethodInfo GetBaseDefinition ()
131 return get_base_definition (this);
134 #if NET_2_0 || BOOTSTRAP_NET_2_0
135 public override ParameterInfo ReturnParameter {
137 return MonoMethodInfo.GetReturnParameterInfo (this);
142 public override Type ReturnType {
144 return MonoMethodInfo.GetReturnType (mhandle);
147 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
149 return MonoMethodInfo.GetReturnParameterInfo (this);
153 public override MethodImplAttributes GetMethodImplementationFlags ()
155 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
158 public override ParameterInfo[] GetParameters ()
160 return MonoMethodInfo.GetParametersInfo (mhandle, this);
164 * InternalInvoke() receives the parameters correctly converted by the
165 * binder to match the types of the method signature.
167 [MethodImplAttribute(MethodImplOptions.InternalCall)]
168 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
170 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
173 binder = Binder.DefaultBinder;
174 ParameterInfo[] pinfo = GetParameters ();
176 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
177 throw new TargetParameterCountException ("parameters do not match signature");
179 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
180 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
181 throw new ArgumentException ("failed to convert parameters");
183 for (int i = 0; i < pinfo.Length; i++)
184 if (parameters[i].GetType() != pinfo[i].ParameterType)
185 throw new ArgumentException ("parameters do not match signature");
189 if (SecurityManager.SecurityEnabled) {
190 // sadly Attributes doesn't tell us which kind of security action this is so
191 // we must do it the hard way - and it also means that we can skip calling
192 // Attribute (which is another an icall)
193 SecurityManager.ReflectedLinkDemandInvoke (this);
198 if (ContainsGenericParameters)
199 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
206 // The ex argument is used to distinguish exceptions thrown by the icall
207 // from the exceptions thrown by the called method (which need to be
208 // wrapped in TargetInvocationException).
209 o = InternalInvoke (obj, parameters, out exc);
211 } catch (ThreadAbortException) {
215 } catch (MethodAccessException) {
218 } catch (Exception e) {
219 throw new TargetInvocationException (e);
227 public override RuntimeMethodHandle MethodHandle {
228 get {return new RuntimeMethodHandle (mhandle);}
230 public override MethodAttributes Attributes {
232 return MonoMethodInfo.GetAttributes (mhandle);
236 public override CallingConventions CallingConvention {
238 return MonoMethodInfo.GetCallingConvention (mhandle);
242 public override Type ReflectedType {
247 public override Type DeclaringType {
249 return MonoMethodInfo.GetDeclaringType (mhandle);
252 public override string Name {
256 return get_name (this);
260 public override bool IsDefined (Type attributeType, bool inherit) {
261 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
264 public override object[] GetCustomAttributes( bool inherit) {
265 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
267 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
268 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
271 [MethodImplAttribute(MethodImplOptions.InternalCall)]
272 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
274 internal object[] GetPseudoCustomAttributes ()
278 /* MS.NET doesn't report MethodImplAttribute */
280 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
281 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
283 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
288 object[] attrs = new object [count];
291 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
292 attrs [count ++] = new PreserveSigAttribute ();
293 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
294 DllImportAttribute attr = GetDllImportAttribute (mhandle);
295 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
296 attr.PreserveSig = true;
297 attrs [count ++] = attr;
303 static bool ShouldPrintFullName (Type type) {
304 return type.IsClass && (!type.IsPointer ||
306 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
308 !type.GetElementType ().IsPrimitive);
312 public override string ToString () {
313 StringBuilder sb = new StringBuilder ();
314 Type retType = ReturnType;
315 if (ShouldPrintFullName (retType))
316 sb.Append (retType.ToString ());
318 sb.Append (retType.Name);
321 #if NET_2_0 || BOOTSTRAP_NET_2_0
322 if (IsGenericMethod) {
323 Type[] gen_params = GetGenericArguments ();
325 for (int j = 0; j < gen_params.Length; j++) {
328 sb.Append (gen_params [j].Name);
334 ParameterInfo[] p = GetParameters ();
335 for (int i = 0; i < p.Length; ++i) {
338 Type pt = p[i].ParameterType;
339 bool byref = pt.IsByRef;
341 pt = pt.GetElementType ();
342 if (ShouldPrintFullName (pt))
343 sb.Append (pt.ToString ());
347 sb.Append (" ByRef");
349 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
356 return sb.ToString ();
361 public void GetObjectData(SerializationInfo info, StreamingContext context)
364 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
365 ? GetGenericArguments () : null;
366 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
368 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
372 #if NET_2_0 || BOOTSTRAP_NET_2_0
373 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
375 if (methodInstantiation == null)
376 throw new ArgumentNullException ("methodInstantiation");
377 foreach (Type type in methodInstantiation)
379 throw new ArgumentNullException ();
381 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
383 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
387 [MethodImplAttribute(MethodImplOptions.InternalCall)]
388 extern MethodInfo MakeGenericMethod_impl (Type [] types);
390 [MethodImplAttribute(MethodImplOptions.InternalCall)]
391 public override extern Type [] GetGenericArguments ();
393 [MethodImplAttribute(MethodImplOptions.InternalCall)]
394 extern MethodInfo GetGenericMethodDefinition_impl ();
396 public override MethodInfo GetGenericMethodDefinition ()
398 MethodInfo res = GetGenericMethodDefinition_impl ();
400 throw new InvalidOperationException ();
405 public override extern bool IsGenericMethodDefinition {
406 [MethodImplAttribute(MethodImplOptions.InternalCall)]
410 public override extern bool IsGenericMethod {
411 [MethodImplAttribute(MethodImplOptions.InternalCall)]
415 public override bool ContainsGenericParameters {
417 if (IsGenericMethod) {
418 foreach (Type arg in GetGenericArguments ())
419 if (arg.ContainsGenericParameters)
422 return DeclaringType.ContainsGenericParameters;
428 public override MethodBody GetMethodBody () {
429 return GetMethodBody (mhandle);
434 internal class MonoCMethod : ConstructorInfo, ISerializable
436 #pragma warning disable 649
437 internal IntPtr mhandle;
440 #pragma warning restore 649
442 public override MethodImplAttributes GetMethodImplementationFlags ()
444 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
447 public override ParameterInfo[] GetParameters ()
449 return MonoMethodInfo.GetParametersInfo (mhandle, this);
453 * InternalInvoke() receives the parameters corretcly converted by the binder
454 * to match the types of the method signature.
456 [MethodImplAttribute(MethodImplOptions.InternalCall)]
457 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
459 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
462 binder = Binder.DefaultBinder;
464 ParameterInfo[] pinfo = GetParameters ();
466 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
467 throw new TargetParameterCountException ("parameters do not match signature");
469 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
470 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
471 throw new ArgumentException ("failed to convert parameters");
473 for (int i = 0; i < pinfo.Length; i++)
474 if (parameters[i].GetType() != pinfo[i].ParameterType)
475 throw new ArgumentException ("parameters do not match signature");
478 if (SecurityManager.SecurityEnabled) {
479 // sadly Attributes doesn't tell us which kind of security action this is so
480 // we must do it the hard way - and it also means that we can skip calling
481 // Attribute (which is another an icall)
482 SecurityManager.ReflectedLinkDemandInvoke (this);
486 if (obj == null && DeclaringType.ContainsGenericParameters)
487 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
490 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
491 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
494 Exception exc = null;
498 o = InternalInvoke (obj, parameters, out exc);
500 } catch (MethodAccessException) {
503 } catch (Exception e) {
504 throw new TargetInvocationException (e);
509 return (obj == null) ? o : null;
512 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
513 return Invoke (null, invokeAttr, binder, parameters, culture);
516 public override RuntimeMethodHandle MethodHandle {
517 get {return new RuntimeMethodHandle (mhandle);}
519 public override MethodAttributes Attributes {
521 return MonoMethodInfo.GetAttributes (mhandle);
525 public override CallingConventions CallingConvention {
527 return MonoMethodInfo.GetCallingConvention (mhandle);
531 public override Type ReflectedType {
536 public override Type DeclaringType {
538 return MonoMethodInfo.GetDeclaringType (mhandle);
541 public override string Name {
545 return MonoMethod.get_name (this);
549 public override bool IsDefined (Type attributeType, bool inherit) {
550 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
553 public override object[] GetCustomAttributes( bool inherit) {
554 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
557 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
558 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
562 public override MethodBody GetMethodBody () {
563 return GetMethodBody (mhandle);
567 public override string ToString () {
568 StringBuilder sb = new StringBuilder ();
572 ParameterInfo[] p = GetParameters ();
573 for (int i = 0; i < p.Length; ++i) {
576 sb.Append (p[i].ParameterType.Name);
578 if (CallingConvention == CallingConventions.Any)
581 return sb.ToString ();
585 public void GetObjectData(SerializationInfo info, StreamingContext context)
587 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);