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 internal CallingConventions callconv;
51 [MethodImplAttribute(MethodImplOptions.InternalCall)]
52 internal static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
54 [MethodImplAttribute(MethodImplOptions.InternalCall)]
55 internal static extern ParameterInfo[] get_parameter_info (IntPtr handle);
57 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58 internal static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
62 * Note: most of this class needs to be duplicated for the contructor, since
63 * the .NET reflection class hierarchy is so broken.
66 internal class MonoMethod : MethodInfo, ISerializable
68 #pragma warning disable 649
69 internal IntPtr mhandle;
72 #pragma warning restore 649
74 internal MonoMethod () {
77 internal MonoMethod (RuntimeMethodHandle mhandle) {
78 this.mhandle = mhandle.Value;
81 [MethodImplAttribute(MethodImplOptions.InternalCall)]
82 internal static extern string get_name (MethodBase method);
84 [MethodImplAttribute(MethodImplOptions.InternalCall)]
85 internal static extern MonoMethod get_base_definition (MonoMethod method);
87 public override MethodInfo GetBaseDefinition ()
89 return get_base_definition (this);
92 #if NET_2_0 || BOOTSTRAP_NET_2_0
93 public override ParameterInfo ReturnParameter {
95 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
100 public override Type ReturnType {
103 MonoMethodInfo.get_method_info (mhandle, out info);
107 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
109 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
113 public override MethodImplAttributes GetMethodImplementationFlags() {
115 MonoMethodInfo.get_method_info (mhandle, out info);
119 public override ParameterInfo[] GetParameters() {
120 return MonoMethodInfo.get_parameter_info (mhandle);
124 * InternalInvoke() receives the parameters correctly converted by the
125 * binder to match the types of the method signature.
127 [MethodImplAttribute(MethodImplOptions.InternalCall)]
128 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
130 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
133 binder = Binder.DefaultBinder;
134 ParameterInfo[] pinfo = GetParameters ();
136 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
137 throw new TargetParameterCountException ("parameters do not match signature");
139 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
140 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
141 throw new ArgumentException ("failed to convert parameters");
143 for (int i = 0; i < pinfo.Length; i++)
144 if (parameters[i].GetType() != pinfo[i].ParameterType)
145 throw new ArgumentException ("parameters do not match signature");
149 if (SecurityManager.SecurityEnabled) {
150 // sadly Attributes doesn't tell us which kind of security action this is so
151 // we must do it the hard way - and it also means that we can skip calling
152 // Attribute (which is another an icall)
153 SecurityManager.ReflectedLinkDemandInvoke (this);
158 if (ContainsGenericParameters)
159 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
166 // The ex argument is used to distinguish exceptions thrown by the icall
167 // from the exceptions thrown by the called method (which need to be
168 // wrapped in TargetInvocationException).
169 o = InternalInvoke (obj, parameters, out exc);
171 } catch (ThreadAbortException) {
175 } catch (MethodAccessException) {
178 } catch (Exception e) {
179 throw new TargetInvocationException (e);
187 public override RuntimeMethodHandle MethodHandle {
188 get {return new RuntimeMethodHandle (mhandle);}
190 public override MethodAttributes Attributes {
193 MonoMethodInfo.get_method_info (mhandle, out info);
198 public override CallingConventions CallingConvention {
201 MonoMethodInfo.get_method_info (mhandle, out info);
202 return info.callconv;
206 public override Type ReflectedType {
211 public override Type DeclaringType {
214 MonoMethodInfo.get_method_info (mhandle, out info);
218 public override string Name {
222 return get_name (this);
226 public override bool IsDefined (Type attributeType, bool inherit) {
227 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
230 public override object[] GetCustomAttributes( bool inherit) {
231 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
233 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
234 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
237 [MethodImplAttribute(MethodImplOptions.InternalCall)]
238 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
240 internal object[] GetPseudoCustomAttributes ()
244 /* MS.NET doesn't report MethodImplAttribute */
247 MonoMethodInfo.get_method_info (mhandle, out info);
248 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
250 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
255 object[] attrs = new object [count];
258 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
259 attrs [count ++] = new PreserveSigAttribute ();
260 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
261 DllImportAttribute attr = GetDllImportAttribute (mhandle);
262 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
263 attr.PreserveSig = true;
264 attrs [count ++] = attr;
270 static bool ShouldPrintFullName (Type type) {
271 return type.IsClass && (!type.IsPointer ||
273 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
275 !type.GetElementType ().IsPrimitive);
279 public override string ToString () {
280 StringBuilder sb = new StringBuilder ();
281 Type retType = ReturnType;
282 if (ShouldPrintFullName (retType))
283 sb.Append (retType.ToString ());
285 sb.Append (retType.Name);
288 #if NET_2_0 || BOOTSTRAP_NET_2_0
289 if (IsGenericMethod) {
290 Type[] gen_params = GetGenericArguments ();
292 for (int j = 0; j < gen_params.Length; j++) {
295 sb.Append (gen_params [j].Name);
301 ParameterInfo[] p = GetParameters ();
302 for (int i = 0; i < p.Length; ++i) {
305 Type pt = p[i].ParameterType;
306 bool byref = pt.IsByRef;
308 pt = pt.GetElementType ();
309 if (ShouldPrintFullName (pt))
310 sb.Append (pt.ToString ());
314 sb.Append (" ByRef");
316 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
323 return sb.ToString ();
328 public void GetObjectData(SerializationInfo info, StreamingContext context)
331 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
332 ? GetGenericArguments () : null;
333 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
335 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
339 #if NET_2_0 || BOOTSTRAP_NET_2_0
340 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
342 if (methodInstantiation == null)
343 throw new ArgumentNullException ("methodInstantiation");
344 foreach (Type type in methodInstantiation)
346 throw new ArgumentNullException ();
348 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
350 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
354 [MethodImplAttribute(MethodImplOptions.InternalCall)]
355 extern MethodInfo MakeGenericMethod_impl (Type [] types);
357 [MethodImplAttribute(MethodImplOptions.InternalCall)]
358 public override extern Type [] GetGenericArguments ();
360 [MethodImplAttribute(MethodImplOptions.InternalCall)]
361 extern MethodInfo GetGenericMethodDefinition_impl ();
363 public override MethodInfo GetGenericMethodDefinition ()
365 MethodInfo res = GetGenericMethodDefinition_impl ();
367 throw new InvalidOperationException ();
372 public override extern bool IsGenericMethodDefinition {
373 [MethodImplAttribute(MethodImplOptions.InternalCall)]
377 public override extern bool IsGenericMethod {
378 [MethodImplAttribute(MethodImplOptions.InternalCall)]
382 public override bool ContainsGenericParameters {
384 if (IsGenericMethod) {
385 foreach (Type arg in GetGenericArguments ())
386 if (arg.ContainsGenericParameters)
389 return DeclaringType.ContainsGenericParameters;
395 public override MethodBody GetMethodBody () {
396 return GetMethodBody (mhandle);
401 internal class MonoCMethod : ConstructorInfo, ISerializable
403 #pragma warning disable 649
404 internal IntPtr mhandle;
407 #pragma warning restore 649
409 public override MethodImplAttributes GetMethodImplementationFlags() {
411 MonoMethodInfo.get_method_info (mhandle, out info);
415 public override ParameterInfo[] GetParameters() {
416 return MonoMethodInfo.get_parameter_info (mhandle);
420 * InternalInvoke() receives the parameters corretcly converted by the binder
421 * to match the types of the method signature.
423 [MethodImplAttribute(MethodImplOptions.InternalCall)]
424 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
426 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
429 binder = Binder.DefaultBinder;
431 ParameterInfo[] pinfo = GetParameters ();
433 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
434 throw new TargetParameterCountException ("parameters do not match signature");
436 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
437 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
438 throw new ArgumentException ("failed to convert parameters");
440 for (int i = 0; i < pinfo.Length; i++)
441 if (parameters[i].GetType() != pinfo[i].ParameterType)
442 throw new ArgumentException ("parameters do not match signature");
445 if (SecurityManager.SecurityEnabled) {
446 // sadly Attributes doesn't tell us which kind of security action this is so
447 // we must do it the hard way - and it also means that we can skip calling
448 // Attribute (which is another an icall)
449 SecurityManager.ReflectedLinkDemandInvoke (this);
453 if (obj == null && DeclaringType.ContainsGenericParameters)
454 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
457 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
458 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
461 Exception exc = null;
465 o = InternalInvoke (obj, parameters, out exc);
467 } catch (MethodAccessException) {
470 } catch (Exception e) {
471 throw new TargetInvocationException (e);
476 return (obj == null) ? o : null;
479 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
480 return Invoke (null, invokeAttr, binder, parameters, culture);
483 public override RuntimeMethodHandle MethodHandle {
484 get {return new RuntimeMethodHandle (mhandle);}
486 public override MethodAttributes Attributes {
489 MonoMethodInfo.get_method_info (mhandle, out info);
494 public override CallingConventions CallingConvention {
497 MonoMethodInfo.get_method_info (mhandle, out info);
498 return info.callconv;
502 public override Type ReflectedType {
507 public override Type DeclaringType {
510 MonoMethodInfo.get_method_info (mhandle, out info);
514 public override string Name {
518 return MonoMethod.get_name (this);
522 public override bool IsDefined (Type attributeType, bool inherit) {
523 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
526 public override object[] GetCustomAttributes( bool inherit) {
527 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
530 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
531 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
535 public override MethodBody GetMethodBody () {
536 return GetMethodBody (mhandle);
540 public override string ToString () {
541 StringBuilder sb = new StringBuilder ();
545 ParameterInfo[] p = GetParameters ();
546 for (int i = 0; i < p.Length; ++i) {
549 sb.Append (p[i].ParameterType.Name);
552 return sb.ToString ();
556 public void GetObjectData(SerializationInfo info, StreamingContext context)
558 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);