2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / class / corlib / System.Reflection / MonoMethod.cs
blobc5fab6487317769146e367d2d6be9f9dd4ddaef5
1 //
2 // System.Reflection/MonoMethod.cs
3 // The class used to represent methods from the mono runtime.
4 //
5 // Author:
6 // Paolo Molaro (lupus@ximian.com)
7 //
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:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
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;
39 using System.Text;
42 namespace System.Reflection {
44 internal struct MonoMethodInfo
46 #pragma warning disable 649
47 private Type parent;
48 private Type ret;
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 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
59 MonoMethodInfo info;
60 MonoMethodInfo.get_method_info (handle, out info);
61 return info;
64 internal static Type GetDeclaringType (IntPtr handle)
66 return GetMethodInfo (handle).parent;
69 internal static Type GetReturnType (IntPtr handle)
71 return GetMethodInfo (handle).ret;
74 internal static MethodAttributes GetAttributes (IntPtr handle)
76 return GetMethodInfo (handle).attrs;
79 internal static CallingConventions GetCallingConvention (IntPtr handle)
81 return GetMethodInfo (handle).callconv;
84 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
86 return GetMethodInfo (handle).iattrs;
89 [MethodImplAttribute(MethodImplOptions.InternalCall)]
90 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
92 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
94 return get_parameter_info (handle, member);
97 [MethodImplAttribute(MethodImplOptions.InternalCall)]
98 static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
100 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
102 return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
107 * Note: most of this class needs to be duplicated for the contructor, since
108 * the .NET reflection class hierarchy is so broken.
110 [Serializable()]
111 internal class MonoMethod : MethodInfo, ISerializable
113 #pragma warning disable 649
114 internal IntPtr mhandle;
115 string name;
116 Type reftype;
117 #pragma warning restore 649
119 internal MonoMethod () {
122 internal MonoMethod (RuntimeMethodHandle mhandle) {
123 this.mhandle = mhandle.Value;
126 [MethodImplAttribute(MethodImplOptions.InternalCall)]
127 internal static extern string get_name (MethodBase method);
129 [MethodImplAttribute(MethodImplOptions.InternalCall)]
130 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
132 public override MethodInfo GetBaseDefinition ()
134 return get_base_method (this, true);
137 internal override MethodInfo GetBaseMethod ()
139 return get_base_method (this, false);
142 public override ParameterInfo ReturnParameter {
143 get {
144 return MonoMethodInfo.GetReturnParameterInfo (this);
148 public override Type ReturnType {
149 get {
150 return MonoMethodInfo.GetReturnType (mhandle);
153 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
154 get {
155 return MonoMethodInfo.GetReturnParameterInfo (this);
159 public override MethodImplAttributes GetMethodImplementationFlags ()
161 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
164 public override ParameterInfo[] GetParameters ()
166 ParameterInfo[] src = MonoMethodInfo.GetParametersInfo (mhandle, this);
167 ParameterInfo[] res = new ParameterInfo [src.Length];
168 src.CopyTo (res, 0);
169 return res;
172 internal override int GetParameterCount ()
174 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
175 return pi == null ? 0 : pi.Length;
179 * InternalInvoke() receives the parameters correctly converted by the
180 * binder to match the types of the method signature.
182 [MethodImplAttribute(MethodImplOptions.InternalCall)]
183 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
185 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
187 if (binder == null)
188 binder = Binder.DefaultBinder;
189 /*Avoid allocating an array every time*/
190 ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
192 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
193 throw new TargetParameterCountException ("parameters do not match signature");
195 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
196 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
197 throw new ArgumentException ("failed to convert parameters");
198 } else {
199 for (int i = 0; i < pinfo.Length; i++)
200 if (parameters[i].GetType() != pinfo[i].ParameterType)
201 throw new ArgumentException ("parameters do not match signature");
204 #if !NET_2_1
205 if (SecurityManager.SecurityEnabled) {
206 // sadly Attributes doesn't tell us which kind of security action this is so
207 // we must do it the hard way - and it also means that we can skip calling
208 // Attribute (which is another an icall)
209 SecurityManager.ReflectedLinkDemandInvoke (this);
211 #endif
213 if (ContainsGenericParameters)
214 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
216 Exception exc;
217 object o = null;
219 try {
220 // The ex argument is used to distinguish exceptions thrown by the icall
221 // from the exceptions thrown by the called method (which need to be
222 // wrapped in TargetInvocationException).
223 o = InternalInvoke (obj, parameters, out exc);
224 } catch (ThreadAbortException) {
225 throw;
226 #if NET_2_1
227 } catch (MethodAccessException) {
228 throw;
229 #endif
230 } catch (Exception e) {
231 throw new TargetInvocationException (e);
234 if (exc != null)
235 throw exc;
236 return o;
239 public override RuntimeMethodHandle MethodHandle {
240 get {return new RuntimeMethodHandle (mhandle);}
242 public override MethodAttributes Attributes {
243 get {
244 return MonoMethodInfo.GetAttributes (mhandle);
248 public override CallingConventions CallingConvention {
249 get {
250 return MonoMethodInfo.GetCallingConvention (mhandle);
254 public override Type ReflectedType {
255 get {
256 return reftype;
259 public override Type DeclaringType {
260 get {
261 return MonoMethodInfo.GetDeclaringType (mhandle);
264 public override string Name {
265 get {
266 if (name != null)
267 return name;
268 return get_name (this);
272 public override bool IsDefined (Type attributeType, bool inherit) {
273 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
276 public override object[] GetCustomAttributes( bool inherit) {
277 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
279 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
280 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
283 [MethodImplAttribute(MethodImplOptions.InternalCall)]
284 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
286 internal object[] GetPseudoCustomAttributes ()
288 int count = 0;
290 /* MS.NET doesn't report MethodImplAttribute */
292 MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
293 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
294 count ++;
295 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
296 count ++;
298 if (count == 0)
299 return null;
300 object[] attrs = new object [count];
301 count = 0;
303 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
304 attrs [count ++] = new PreserveSigAttribute ();
305 if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
306 DllImportAttribute attr = GetDllImportAttribute (mhandle);
307 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
308 attr.PreserveSig = true;
309 attrs [count ++] = attr;
312 return attrs;
315 static bool ShouldPrintFullName (Type type) {
316 return type.IsClass && (!type.IsPointer ||
317 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
320 public override string ToString () {
321 StringBuilder sb = new StringBuilder ();
322 Type retType = ReturnType;
323 if (ShouldPrintFullName (retType))
324 sb.Append (retType.ToString ());
325 else
326 sb.Append (retType.Name);
327 sb.Append (" ");
328 sb.Append (Name);
329 if (IsGenericMethod) {
330 Type[] gen_params = GetGenericArguments ();
331 sb.Append ("[");
332 for (int j = 0; j < gen_params.Length; j++) {
333 if (j > 0)
334 sb.Append (",");
335 sb.Append (gen_params [j].Name);
337 sb.Append ("]");
339 sb.Append ("(");
340 ParameterInfo[] p = GetParameters ();
341 for (int i = 0; i < p.Length; ++i) {
342 if (i > 0)
343 sb.Append (", ");
344 Type pt = p[i].ParameterType;
345 bool byref = pt.IsByRef;
346 if (byref)
347 pt = pt.GetElementType ();
348 if (ShouldPrintFullName (pt))
349 sb.Append (pt.ToString ());
350 else
351 sb.Append (pt.Name);
352 if (byref)
353 sb.Append (" ByRef");
355 if ((CallingConvention & CallingConventions.VarArgs) != 0) {
356 if (p.Length > 0)
357 sb.Append (", ");
358 sb.Append ("...");
361 sb.Append (")");
362 return sb.ToString ();
366 // ISerializable
367 public void GetObjectData(SerializationInfo info, StreamingContext context)
369 Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
370 ? GetGenericArguments () : null;
371 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
374 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
376 if (methodInstantiation == null)
377 throw new ArgumentNullException ("methodInstantiation");
379 if (!IsGenericMethodDefinition)
380 throw new InvalidOperationException ("not a generic method definition");
382 /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
383 if (GetGenericArguments ().Length != methodInstantiation.Length)
384 throw new ArgumentException ("Incorrect length");
386 bool hasUserType = false;
387 foreach (Type type in methodInstantiation) {
388 if (type == null)
389 throw new ArgumentNullException ();
390 if (!(type is MonoType))
391 hasUserType = true;
394 if (hasUserType)
395 return new MethodOnTypeBuilderInst (this, methodInstantiation);
397 MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
398 if (ret == null)
399 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
400 return ret;
403 [MethodImplAttribute(MethodImplOptions.InternalCall)]
404 extern MethodInfo MakeGenericMethod_impl (Type [] types);
406 [MethodImplAttribute(MethodImplOptions.InternalCall)]
407 public override extern Type [] GetGenericArguments ();
409 [MethodImplAttribute(MethodImplOptions.InternalCall)]
410 extern MethodInfo GetGenericMethodDefinition_impl ();
412 public override MethodInfo GetGenericMethodDefinition ()
414 MethodInfo res = GetGenericMethodDefinition_impl ();
415 if (res == null)
416 throw new InvalidOperationException ();
418 return res;
421 public override extern bool IsGenericMethodDefinition {
422 [MethodImplAttribute(MethodImplOptions.InternalCall)]
423 get;
426 public override extern bool IsGenericMethod {
427 [MethodImplAttribute(MethodImplOptions.InternalCall)]
428 get;
431 public override bool ContainsGenericParameters {
432 get {
433 if (IsGenericMethod) {
434 foreach (Type arg in GetGenericArguments ())
435 if (arg.ContainsGenericParameters)
436 return true;
438 return DeclaringType.ContainsGenericParameters;
442 public override MethodBody GetMethodBody () {
443 return GetMethodBody (mhandle);
446 #if NET_4_0
447 public override IList<CustomAttributeData> GetCustomAttributesData () {
448 return CustomAttributeData.GetCustomAttributes (this);
450 #endif
453 internal class MonoCMethod : ConstructorInfo, ISerializable
455 #pragma warning disable 649
456 internal IntPtr mhandle;
457 string name;
458 Type reftype;
459 #pragma warning restore 649
461 public override MethodImplAttributes GetMethodImplementationFlags ()
463 return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
466 public override ParameterInfo[] GetParameters ()
468 return MonoMethodInfo.GetParametersInfo (mhandle, this);
471 internal override int GetParameterCount ()
473 var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
474 return pi == null ? 0 : pi.Length;
478 * InternalInvoke() receives the parameters corretcly converted by the binder
479 * to match the types of the method signature.
481 [MethodImplAttribute(MethodImplOptions.InternalCall)]
482 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
484 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
486 if (binder == null)
487 binder = Binder.DefaultBinder;
489 ParameterInfo[] pinfo = GetParameters ();
491 if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
492 throw new TargetParameterCountException ("parameters do not match signature");
494 if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
495 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
496 throw new ArgumentException ("failed to convert parameters");
497 } else {
498 for (int i = 0; i < pinfo.Length; i++)
499 if (parameters[i].GetType() != pinfo[i].ParameterType)
500 throw new ArgumentException ("parameters do not match signature");
503 #if !NET_2_1
504 if (SecurityManager.SecurityEnabled) {
505 // sadly Attributes doesn't tell us which kind of security action this is so
506 // we must do it the hard way - and it also means that we can skip calling
507 // Attribute (which is another an icall)
508 SecurityManager.ReflectedLinkDemandInvoke (this);
510 #endif
512 if (obj == null && DeclaringType.ContainsGenericParameters)
513 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
515 if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
516 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
519 Exception exc = null;
520 object o = null;
522 try {
523 o = InternalInvoke (obj, parameters, out exc);
524 #if NET_2_1
525 } catch (MethodAccessException) {
526 throw;
527 #endif
528 } catch (Exception e) {
529 throw new TargetInvocationException (e);
532 if (exc != null)
533 throw exc;
534 return (obj == null) ? o : null;
537 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
538 return Invoke (null, invokeAttr, binder, parameters, culture);
541 public override RuntimeMethodHandle MethodHandle {
542 get {return new RuntimeMethodHandle (mhandle);}
544 public override MethodAttributes Attributes {
545 get {
546 return MonoMethodInfo.GetAttributes (mhandle);
550 public override CallingConventions CallingConvention {
551 get {
552 return MonoMethodInfo.GetCallingConvention (mhandle);
556 public override Type ReflectedType {
557 get {
558 return reftype;
561 public override Type DeclaringType {
562 get {
563 return MonoMethodInfo.GetDeclaringType (mhandle);
566 public override string Name {
567 get {
568 if (name != null)
569 return name;
570 return MonoMethod.get_name (this);
574 public override bool IsDefined (Type attributeType, bool inherit) {
575 return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
578 public override object[] GetCustomAttributes( bool inherit) {
579 return MonoCustomAttrs.GetCustomAttributes (this, inherit);
582 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
583 return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
586 public override MethodBody GetMethodBody () {
587 return GetMethodBody (mhandle);
590 public override string ToString () {
591 StringBuilder sb = new StringBuilder ();
592 sb.Append ("Void ");
593 sb.Append (Name);
594 sb.Append ("(");
595 ParameterInfo[] p = GetParameters ();
596 for (int i = 0; i < p.Length; ++i) {
597 if (i > 0)
598 sb.Append (", ");
599 sb.Append (p[i].ParameterType.Name);
601 if (CallingConvention == CallingConventions.Any)
602 sb.Append (", ...");
603 sb.Append (")");
604 return sb.ToString ();
607 // ISerializable
608 public void GetObjectData(SerializationInfo info, StreamingContext context)
610 MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
613 #if NET_4_0
614 public override IList<CustomAttributeData> GetCustomAttributesData () {
615 return CustomAttributeData.GetCustomAttributes (this);
617 #endif