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
45 #pragma warning disable 649
48 internal MethodAttributes attrs;
49 internal MethodImplAttributes iattrs;
50 private CallingConventions callconv;
51 #pragma warning restore 649
53 [MethodImplAttribute(MethodImplOptions.InternalCall)]
54 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
56 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
59 MonoMethodInfo.get_method_info (handle, out info);
63 internal static Type GetDeclaringType (IntPtr handle)
65 return GetMethodInfo (handle).parent;
68 internal static Type GetReturnType (IntPtr handle)
70 return GetMethodInfo (handle).ret;
73 internal static MethodAttributes GetAttributes (IntPtr handle)
75 return GetMethodInfo (handle).attrs;
78 internal static CallingConventions GetCallingConvention (IntPtr handle)
80 return GetMethodInfo (handle).callconv;
83 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
85 return GetMethodInfo (handle).iattrs;
88 [MethodImplAttribute(MethodImplOptions.InternalCall)]
89 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
91 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
93 return get_parameter_info (handle, member);
96 [MethodImplAttribute(MethodImplOptions.InternalCall)]
97 static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
99 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
101 return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
106 * Note: most of this class needs to be duplicated for the contructor, since
107 * the .NET reflection class hierarchy is so broken.
110 internal class MonoMethod : MethodInfo, ISerializable
112 #pragma warning disable 649
113 internal IntPtr mhandle;
116 #pragma warning restore 649
118 internal MonoMethod () {
121 internal MonoMethod (RuntimeMethodHandle mhandle) {
122 this.mhandle = mhandle.Value;
125 [MethodImplAttribute(MethodImplOptions.InternalCall)]
126 internal static extern string get_name (MethodBase method);
128 [MethodImplAttribute(MethodImplOptions.InternalCall)]
129 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
131 public override MethodInfo GetBaseDefinition ()
133 return get_base_method (this, true);
136 internal override MethodInfo GetBaseMethod ()
138 return get_base_method (this, false);
141 public override ParameterInfo ReturnParameter {
143 return MonoMethodInfo.GetReturnParameterInfo (this);
147 public override Type ReturnType {
149 return MonoMethodInfo.GetReturnType (mhandle);
152 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
154 return MonoMethodInfo.GetReturnParameterInfo (this);
158 public override MethodImplAttributes GetMethodImplementationFlags ()
160 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
163 public override ParameterInfo[] GetParameters ()
165 return MonoMethodInfo.GetParametersInfo (mhandle, this);
169 * InternalInvoke() receives the parameters correctly converted by the
170 * binder to match the types of the method signature.
172 [MethodImplAttribute(MethodImplOptions.InternalCall)]
173 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
175 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
178 binder = Binder.DefaultBinder;
179 ParameterInfo[] pinfo = GetParameters ();
181 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
182 throw new TargetParameterCountException ("parameters do not match signature");
184 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
185 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
186 throw new ArgumentException ("failed to convert parameters");
188 for (int i = 0; i < pinfo.Length; i++)
189 if (parameters[i].GetType() != pinfo[i].ParameterType)
190 throw new ArgumentException ("parameters do not match signature");
194 if (SecurityManager.SecurityEnabled) {
195 // sadly Attributes doesn't tell us which kind of security action this is so
196 // we must do it the hard way - and it also means that we can skip calling
197 // Attribute (which is another an icall)
198 SecurityManager.ReflectedLinkDemandInvoke (this);
202 if (ContainsGenericParameters)
203 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
209 // The ex argument is used to distinguish exceptions thrown by the icall
210 // from the exceptions thrown by the called method (which need to be
211 // wrapped in TargetInvocationException).
212 o = InternalInvoke (obj, parameters, out exc);
213 } catch (ThreadAbortException) {
216 } catch (MethodAccessException) {
219 } catch (Exception e) {
220 throw new TargetInvocationException (e);
228 public override RuntimeMethodHandle MethodHandle {
229 get {return new RuntimeMethodHandle (mhandle);}
231 public override MethodAttributes Attributes {
233 return MonoMethodInfo.GetAttributes (mhandle);
237 public override CallingConventions CallingConvention {
239 return MonoMethodInfo.GetCallingConvention (mhandle);
243 public override Type ReflectedType {
248 public override Type DeclaringType {
250 return MonoMethodInfo.GetDeclaringType (mhandle);
253 public override string Name {
257 return get_name (this);
261 public override bool IsDefined (Type attributeType, bool inherit) {
262 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
265 public override object[] GetCustomAttributes( bool inherit) {
266 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
268 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
269 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
272 [MethodImplAttribute(MethodImplOptions.InternalCall)]
273 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
275 internal object[] GetPseudoCustomAttributes ()
279 /* MS.NET doesn't report MethodImplAttribute */
281 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
282 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
284 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
289 object[] attrs = new object [count];
292 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
293 attrs [count ++] = new PreserveSigAttribute ();
294 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
295 DllImportAttribute attr = GetDllImportAttribute (mhandle);
296 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
297 attr.PreserveSig = true;
298 attrs [count ++] = attr;
304 static bool ShouldPrintFullName (Type type) {
305 return type.IsClass && (!type.IsPointer ||
306 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
309 public override string ToString () {
310 StringBuilder sb = new StringBuilder ();
311 Type retType = ReturnType;
312 if (ShouldPrintFullName (retType))
313 sb.Append (retType.ToString ());
315 sb.Append (retType.Name);
318 if (IsGenericMethod) {
319 Type[] gen_params = GetGenericArguments ();
321 for (int j = 0; j < gen_params.Length; j++) {
324 sb.Append (gen_params [j].Name);
329 ParameterInfo[] p = GetParameters ();
330 for (int i = 0; i < p.Length; ++i) {
333 Type pt = p[i].ParameterType;
334 bool byref = pt.IsByRef;
336 pt = pt.GetElementType ();
337 if (ShouldPrintFullName (pt))
338 sb.Append (pt.ToString ());
342 sb.Append (" ByRef");
344 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
351 return sb.ToString ();
356 public void GetObjectData(SerializationInfo info, StreamingContext context)
358 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
359 ? GetGenericArguments () : null;
360 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
363 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
365 if (methodInstantiation == null)
366 throw new ArgumentNullException ("methodInstantiation");
368 if (!IsGenericMethodDefinition)
369 throw new InvalidOperationException ("not a generic method definition");
371 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
372 if (GetGenericArguments ().Length != methodInstantiation.Length)
373 throw new ArgumentException ("Incorrect length");
375 bool hasUserType = false;
376 foreach (Type type in methodInstantiation) {
378 throw new ArgumentNullException ();
379 if (!(type is MonoType))
384 return new MethodOnTypeBuilderInst (this, methodInstantiation);
386 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
388 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
392 [MethodImplAttribute(MethodImplOptions.InternalCall)]
393 extern MethodInfo MakeGenericMethod_impl (Type [] types);
395 [MethodImplAttribute(MethodImplOptions.InternalCall)]
396 public override extern Type [] GetGenericArguments ();
398 [MethodImplAttribute(MethodImplOptions.InternalCall)]
399 extern MethodInfo GetGenericMethodDefinition_impl ();
401 public override MethodInfo GetGenericMethodDefinition ()
403 MethodInfo res = GetGenericMethodDefinition_impl ();
405 throw new InvalidOperationException ();
410 public override extern bool IsGenericMethodDefinition {
411 [MethodImplAttribute(MethodImplOptions.InternalCall)]
415 public override extern bool IsGenericMethod {
416 [MethodImplAttribute(MethodImplOptions.InternalCall)]
420 public override bool ContainsGenericParameters {
422 if (IsGenericMethod) {
423 foreach (Type arg in GetGenericArguments ())
424 if (arg.ContainsGenericParameters)
427 return DeclaringType.ContainsGenericParameters;
431 public override MethodBody GetMethodBody () {
432 return GetMethodBody (mhandle);
436 internal class MonoCMethod : ConstructorInfo, ISerializable
438 #pragma warning disable 649
439 internal IntPtr mhandle;
442 #pragma warning restore 649
444 public override MethodImplAttributes GetMethodImplementationFlags ()
446 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
449 public override ParameterInfo[] GetParameters ()
451 return MonoMethodInfo.GetParametersInfo (mhandle, this);
455 * InternalInvoke() receives the parameters corretcly converted by the binder
456 * to match the types of the method signature.
458 [MethodImplAttribute(MethodImplOptions.InternalCall)]
459 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
461 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
464 binder = Binder.DefaultBinder;
466 ParameterInfo[] pinfo = GetParameters ();
468 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
469 throw new TargetParameterCountException ("parameters do not match signature");
471 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
472 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
473 throw new ArgumentException ("failed to convert parameters");
475 for (int i = 0; i < pinfo.Length; i++)
476 if (parameters[i].GetType() != pinfo[i].ParameterType)
477 throw new ArgumentException ("parameters do not match signature");
481 if (SecurityManager.SecurityEnabled) {
482 // sadly Attributes doesn't tell us which kind of security action this is so
483 // we must do it the hard way - and it also means that we can skip calling
484 // Attribute (which is another an icall)
485 SecurityManager.ReflectedLinkDemandInvoke (this);
489 if (obj == null && DeclaringType.ContainsGenericParameters)
490 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
492 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
493 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
496 Exception exc = null;
500 o = InternalInvoke (obj, parameters, out exc);
502 } catch (MethodAccessException) {
505 } catch (Exception e) {
506 throw new TargetInvocationException (e);
511 return (obj == null) ? o : null;
514 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
515 return Invoke (null, invokeAttr, binder, parameters, culture);
518 public override RuntimeMethodHandle MethodHandle {
519 get {return new RuntimeMethodHandle (mhandle);}
521 public override MethodAttributes Attributes {
523 return MonoMethodInfo.GetAttributes (mhandle);
527 public override CallingConventions CallingConvention {
529 return MonoMethodInfo.GetCallingConvention (mhandle);
533 public override Type ReflectedType {
538 public override Type DeclaringType {
540 return MonoMethodInfo.GetDeclaringType (mhandle);
543 public override string Name {
547 return MonoMethod.get_name (this);
551 public override bool IsDefined (Type attributeType, bool inherit) {
552 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
555 public override object[] GetCustomAttributes( bool inherit) {
556 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
559 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
560 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
563 public override MethodBody GetMethodBody () {
564 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);