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
;
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 internal static MonoMethodInfo
GetMethodInfo (IntPtr handle
)
60 MonoMethodInfo
.get_method_info (handle
, out 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.
111 internal class MonoMethod
: MethodInfo
, ISerializable
113 #pragma warning disable 649
114 internal IntPtr mhandle
;
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
{
144 return MonoMethodInfo
.GetReturnParameterInfo (this);
148 public override Type ReturnType
{
150 return MonoMethodInfo
.GetReturnType (mhandle
);
153 public override ICustomAttributeProvider ReturnTypeCustomAttributes
{
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
];
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
)
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");
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");
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);
213 if (ContainsGenericParameters
)
214 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
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
) {
227 } catch (MethodAccessException
) {
230 } catch (Exception e
) {
231 throw new TargetInvocationException (e
);
239 public override RuntimeMethodHandle MethodHandle
{
240 get {return new RuntimeMethodHandle (mhandle);}
242 public override MethodAttributes Attributes
{
244 return MonoMethodInfo
.GetAttributes (mhandle
);
248 public override CallingConventions CallingConvention
{
250 return MonoMethodInfo
.GetCallingConvention (mhandle
);
254 public override Type ReflectedType
{
259 public override Type DeclaringType
{
261 return MonoMethodInfo
.GetDeclaringType (mhandle
);
264 public override string 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 ()
290 /* MS.NET doesn't report MethodImplAttribute */
292 MonoMethodInfo info
= MonoMethodInfo
.GetMethodInfo (mhandle
);
293 if ((info
.iattrs
& MethodImplAttributes
.PreserveSig
) != 0)
295 if ((info
.attrs
& MethodAttributes
.PinvokeImpl
) != 0)
300 object[] attrs
= new object [count
];
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
;
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 ());
326 sb
.Append (retType
.Name
);
329 if (IsGenericMethod
) {
330 Type
[] gen_params
= GetGenericArguments ();
332 for (int j
= 0; j
< gen_params
.Length
; j
++) {
335 sb
.Append (gen_params
[j
].Name
);
340 ParameterInfo
[] p
= GetParameters ();
341 for (int i
= 0; i
< p
.Length
; ++i
) {
344 Type pt
= p
[i
].ParameterType
;
345 bool byref
= pt
.IsByRef
;
347 pt
= pt
.GetElementType ();
348 if (ShouldPrintFullName (pt
))
349 sb
.Append (pt
.ToString ());
353 sb
.Append (" ByRef");
355 if ((CallingConvention
& CallingConventions
.VarArgs
) != 0) {
362 return sb
.ToString ();
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
) {
389 throw new ArgumentNullException ();
390 if (!(type
is MonoType
))
395 return new MethodOnTypeBuilderInst (this, methodInstantiation
);
397 MethodInfo ret
= MakeGenericMethod_impl (methodInstantiation
);
399 throw new ArgumentException (String
.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length
, methodInstantiation
.Length
));
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 ();
416 throw new InvalidOperationException ();
421 public override extern bool IsGenericMethodDefinition
{
422 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
426 public override extern bool IsGenericMethod
{
427 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
431 public override bool ContainsGenericParameters
{
433 if (IsGenericMethod
) {
434 foreach (Type arg
in GetGenericArguments ())
435 if (arg
.ContainsGenericParameters
)
438 return DeclaringType
.ContainsGenericParameters
;
442 public override MethodBody
GetMethodBody () {
443 return GetMethodBody (mhandle
);
447 public override IList
<CustomAttributeData
> GetCustomAttributesData () {
448 return CustomAttributeData
.GetCustomAttributes (this);
453 internal class MonoCMethod
: ConstructorInfo
, ISerializable
455 #pragma warning disable 649
456 internal IntPtr mhandle
;
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
)
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");
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");
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);
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;
523 o
= InternalInvoke (obj
, parameters
, out exc
);
525 } catch (MethodAccessException
) {
528 } catch (Exception e
) {
529 throw new TargetInvocationException (e
);
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
{
546 return MonoMethodInfo
.GetAttributes (mhandle
);
550 public override CallingConventions CallingConvention
{
552 return MonoMethodInfo
.GetCallingConvention (mhandle
);
556 public override Type ReflectedType
{
561 public override Type DeclaringType
{
563 return MonoMethodInfo
.GetDeclaringType (mhandle
);
566 public override string 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 ();
595 ParameterInfo
[] p
= GetParameters ();
596 for (int i
= 0; i
< p
.Length
; ++i
) {
599 sb
.Append (p
[i
].ParameterType
.Name
);
601 if (CallingConvention
== CallingConventions
.Any
)
604 return sb
.ToString ();
608 public void GetObjectData(SerializationInfo info
, StreamingContext context
)
610 MemberInfoSerializationHolder
.Serialize ( info
, Name
, ReflectedType
, ToString(), MemberTypes
.Constructor
);
614 public override IList
<CustomAttributeData
> GetCustomAttributesData () {
615 return CustomAttributeData
.GetCustomAttributes (this);