4d1c13986f3004c830367325c990c52060cb6deb
[mono.git] / mcs / class / corlib / System.Reflection / MonoMethod.cs
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)
10 //
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.
29 //
30
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;
38 using System.Text;
39
40
41 namespace System.Reflection {
42         
43         internal struct MonoMethodInfo 
44         {
45                 internal Type parent;
46                 internal Type ret;
47                 internal MethodAttributes attrs;
48                 internal MethodImplAttributes iattrs;
49                 internal CallingConventions callconv;
50
51                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
52                 internal static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
53                 
54                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
55                 internal static extern ParameterInfo[] get_parameter_info (IntPtr handle);
56
57                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58                 internal static extern UnmanagedMarshal get_retval_marshal (IntPtr handle);
59         };
60         
61         /*
62          * Note: most of this class needs to be duplicated for the contructor, since
63          * the .NET reflection class hierarchy is so broken.
64          */
65         [Serializable()]
66         internal class MonoMethod : MethodInfo, ISerializable
67         {
68                 internal IntPtr mhandle;
69                 string name;
70                 Type reftype;
71
72                 internal MonoMethod () {
73                 }
74
75                 internal MonoMethod (RuntimeMethodHandle mhandle) {
76                         this.mhandle = mhandle.Value;
77                 }
78                 
79                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
80                 internal static extern string get_name (MethodBase method);
81
82                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
83                 internal static extern MonoMethod get_base_definition (MonoMethod method);
84
85                 public override MethodInfo GetBaseDefinition ()
86                 {
87                         return get_base_definition (this);
88                 }
89
90 #if NET_2_0 || BOOTSTRAP_NET_2_0
91                 public override ParameterInfo ReturnParameter {
92                         get {
93                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
94                         }
95                 }
96 #endif
97
98                 public override Type ReturnType {
99                         get {
100                                 MonoMethodInfo info;
101                                 MonoMethodInfo.get_method_info (mhandle, out info);
102                                 return info.ret;
103                         }
104                 }
105                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
106                         get {
107                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
108                         }
109                 }
110                 
111                 public override MethodImplAttributes GetMethodImplementationFlags() {
112                         MonoMethodInfo info;
113                         MonoMethodInfo.get_method_info (mhandle, out info);
114                         return info.iattrs;
115                 }
116
117                 public override ParameterInfo[] GetParameters() {
118                         return MonoMethodInfo.get_parameter_info (mhandle);
119                 }
120
121                 /*
122                  * InternalInvoke() receives the parameters correctly converted by the 
123                  * binder to match the types of the method signature.
124                  */
125                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
126                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
127                 
128                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
129                 {
130                         if (binder == null)
131                                 binder = Binder.DefaultBinder;
132                         ParameterInfo[] pinfo = GetParameters ();
133                         if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
134                                 throw new ArgumentException ("parameters");
135
136                         if (SecurityManager.SecurityEnabled) {
137                                 // sadly Attributes doesn't tell us which kind of security action this is so
138                                 // we must do it the hard way - and it also means that we can skip calling
139                                 // Attribute (which is another an icall)
140                                 SecurityManager.ReflectedLinkDemandInvoke (this);
141                         }
142
143 #if NET_2_0
144                         if (ContainsGenericParameters)
145                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
146 #endif
147
148                         Exception exc;
149                         object o = null;
150
151                         try {
152                                 // The ex argument is used to distinguish exceptions thrown by the icall
153                                 // from the exceptions thrown by the called method (which need to be
154                                 // wrapped in TargetInvocationException).
155                                 o = InternalInvoke (obj, parameters, out exc);
156 #if NET_2_0
157                         } catch (ThreadAbortException) {
158                                 throw;
159 #endif
160 #if NET_2_1
161                         } catch (MethodAccessException) {
162                                 throw;
163 #endif
164                         } catch (Exception e) {
165                                 throw new TargetInvocationException (e);
166                         }
167
168                         if (exc != null)
169                                 throw exc;
170                         return o;
171                 }
172
173                 public override RuntimeMethodHandle MethodHandle { 
174                         get {return new RuntimeMethodHandle (mhandle);} 
175                 }
176                 public override MethodAttributes Attributes { 
177                         get {
178                                 MonoMethodInfo info;
179                                 MonoMethodInfo.get_method_info (mhandle, out info);
180                                 return info.attrs;
181                         } 
182                 }
183
184                 public override CallingConventions CallingConvention { 
185                         get {
186                                 MonoMethodInfo info;
187                                 MonoMethodInfo.get_method_info (mhandle, out info);
188                                 return info.callconv;
189                         }
190                 }
191                 
192                 public override Type ReflectedType {
193                         get {
194                                 return reftype;
195                         }
196                 }
197                 public override Type DeclaringType {
198                         get {
199                                 MonoMethodInfo info;
200                                 MonoMethodInfo.get_method_info (mhandle, out info);
201                                 return info.parent;
202                         }
203                 }
204                 public override string Name {
205                         get {
206                                 if (name != null)
207                                         return name;
208                                 return get_name (this);
209                         }
210                 }
211                 
212                 public override bool IsDefined (Type attributeType, bool inherit) {
213                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
214                 }
215
216                 public override object[] GetCustomAttributes( bool inherit) {
217                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
218                 }
219                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
220                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
221                 }
222
223                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
224                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
225
226                 internal object[] GetPseudoCustomAttributes ()
227                 {
228                         int count = 0;
229
230                         /* MS.NET doesn't report MethodImplAttribute */
231
232                         MonoMethodInfo info;
233                         MonoMethodInfo.get_method_info (mhandle, out info);
234                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
235                                 count ++;
236                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
237                                 count ++;
238                         
239                         if (count == 0)
240                                 return null;
241                         object[] attrs = new object [count];
242                         count = 0;
243
244                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
245                                 attrs [count ++] = new PreserveSigAttribute ();
246                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
247                                 DllImportAttribute attr = GetDllImportAttribute (mhandle);
248                                 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
249                                         attr.PreserveSig = true;
250                                 attrs [count ++] = attr;
251                         }
252
253                         return attrs;
254                 }
255
256                 public override string ToString () {
257                         StringBuilder sb = new StringBuilder ();
258                         if (ReturnType.IsClass)
259                                 sb.Append (ReturnType.ToString ());
260                         else
261                                 sb.Append (ReturnType.Name);
262                         sb.Append (" ");
263                         sb.Append (Name);
264 #if NET_2_0 || BOOTSTRAP_NET_2_0
265                         if (IsGenericMethod) {
266                                 Type[] gen_params = GetGenericArguments ();
267                                 sb.Append ("[");
268                                 for (int j = 0; j < gen_params.Length; j++) {
269                                         if (j > 0)
270                                                 sb.Append (",");
271                                         sb.Append (gen_params [j].Name);
272                                 }
273                                 sb.Append ("]");
274                         }
275 #endif
276                         sb.Append ("(");
277                         ParameterInfo[] p = GetParameters ();
278                         for (int i = 0; i < p.Length; ++i) {
279                                 if (i > 0)
280                                         sb.Append (", ");
281                                 Type pt = p[i].ParameterType;
282                                 bool byref = pt.IsByRef;
283                                 if (byref)
284                                         pt = pt.GetElementType ();
285                                 if (pt.IsClass)
286                                         sb.Append (pt.ToString ());
287                                 else
288                                         sb.Append (pt.Name);
289                                 if (byref)
290                                         sb.Append (" ByRef");
291                         }
292                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
293                                 if (p.Length > 0)
294                                         sb.Append (", ");
295                                 sb.Append ("...");
296                         }
297                         
298                         sb.Append (")");
299                         return sb.ToString ();
300                 }
301
302         
303                 // ISerializable
304                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
305                 {
306 #if NET_2_0
307                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
308                                 ? GetGenericArguments () : null;
309                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
310 #else
311                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
312 #endif
313                 }
314
315 #if NET_2_0 || BOOTSTRAP_NET_2_0
316                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
317                 {
318                         if (methodInstantiation == null)
319                                 throw new ArgumentNullException ("methodInstantiation");
320                         foreach (Type type in methodInstantiation)
321                                 if (type == null)
322                                         throw new ArgumentNullException ();
323
324                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
325                         if (ret == null)
326                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
327                         return ret;
328                 }
329
330                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
331                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
332
333                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
334                 public override extern Type [] GetGenericArguments ();
335
336                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
337                 extern MethodInfo GetGenericMethodDefinition_impl ();
338
339                 public override MethodInfo GetGenericMethodDefinition ()
340                 {
341                         MethodInfo res = GetGenericMethodDefinition_impl ();
342                         if (res == null)
343                                 throw new InvalidOperationException ();
344
345                         return res;
346                 }
347
348                 public override extern bool IsGenericMethodDefinition {
349                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
350                         get;
351                 }
352
353                 public override extern bool IsGenericMethod {
354                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
355                         get;
356                 }
357
358                 public override bool ContainsGenericParameters {
359                         get {
360                                 if (IsGenericMethod) {
361                                         foreach (Type arg in GetGenericArguments ())
362                                                 if (arg.ContainsGenericParameters)
363                                                         return true;
364                                 }
365                                 return DeclaringType.ContainsGenericParameters;
366                         }
367                 }
368 #endif
369
370 #if NET_2_0
371                 public override MethodBody GetMethodBody () {
372                         return GetMethodBody (mhandle);
373                 }
374 #endif
375         }
376         
377         internal class MonoCMethod : ConstructorInfo, ISerializable
378         {
379                 internal IntPtr mhandle;
380                 string name;
381                 Type reftype;
382                 
383                 public override MethodImplAttributes GetMethodImplementationFlags() {
384                         MonoMethodInfo info;
385                         MonoMethodInfo.get_method_info (mhandle, out info);
386                         return info.iattrs;
387                 }
388
389                 public override ParameterInfo[] GetParameters() {
390                         return MonoMethodInfo.get_parameter_info (mhandle);
391                 }
392
393                 /*
394                  * InternalInvoke() receives the parameters corretcly converted by the binder
395                  * to match the types of the method signature.
396                  */
397                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
398                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
399
400                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
401                 {
402                         if (binder == null)
403                                 binder = Binder.DefaultBinder;
404                         ParameterInfo[] pinfo = GetParameters ();
405                         if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
406                                 throw new ArgumentException ("parameters");
407
408                         if (SecurityManager.SecurityEnabled) {
409                                 // sadly Attributes doesn't tell us which kind of security action this is so
410                                 // we must do it the hard way - and it also means that we can skip calling
411                                 // Attribute (which is another an icall)
412                                 SecurityManager.ReflectedLinkDemandInvoke (this);
413                         }
414
415                         Exception exc = null;
416                         object o = null;
417
418                         try {
419                                 o = InternalInvoke (obj, parameters, out exc);
420 #if NET_2_1
421                         } catch (MethodAccessException) {
422                                 throw;
423 #endif
424                         } catch (Exception e) {
425                                 throw new TargetInvocationException (e);
426                         }
427
428                         if (exc != null)
429                                 throw exc;
430                         return o;
431                 }
432
433                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
434                         return Invoke (null, invokeAttr, binder, parameters, culture);
435                 }
436
437                 public override RuntimeMethodHandle MethodHandle { 
438                         get {return new RuntimeMethodHandle (mhandle);} 
439                 }
440                 public override MethodAttributes Attributes { 
441                         get {
442                                 MonoMethodInfo info;
443                                 MonoMethodInfo.get_method_info (mhandle, out info);
444                                 return info.attrs;
445                         } 
446                 }
447
448                 public override CallingConventions CallingConvention { 
449                         get {
450                                 MonoMethodInfo info;
451                                 MonoMethodInfo.get_method_info (mhandle, out info);
452                                 return info.callconv;
453                         }
454                 }
455                 
456                 public override Type ReflectedType {
457                         get {
458                                 return reftype;
459                         }
460                 }
461                 public override Type DeclaringType {
462                         get {
463                                 MonoMethodInfo info;
464                                 MonoMethodInfo.get_method_info (mhandle, out info);
465                                 return info.parent;
466                         }
467                 }
468                 public override string Name {
469                         get {
470                                 if (name != null)
471                                         return name;
472                                 return MonoMethod.get_name (this);
473                         }
474                 }
475
476                 public override bool IsDefined (Type attributeType, bool inherit) {
477                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
478                 }
479
480                 public override object[] GetCustomAttributes( bool inherit) {
481                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
482                 }
483
484                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
485                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
486                 }
487
488 #if NET_2_0
489                 public override MethodBody GetMethodBody () {
490                         return GetMethodBody (mhandle);
491                 }
492 #endif
493
494                 public override string ToString () {
495                         StringBuilder sb = new StringBuilder ();
496                         sb.Append ("Void ");
497                         sb.Append (Name);
498                         sb.Append ("(");
499                         ParameterInfo[] p = GetParameters ();
500                         for (int i = 0; i < p.Length; ++i) {
501                                 if (i > 0)
502                                         sb.Append (", ");
503                                 sb.Append (p[i].ParameterType.Name);
504                         }
505                         sb.Append (")");
506                         return sb.ToString ();
507                 }
508
509                 // ISerializable
510                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
511                 {
512                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
513                 }
514         }
515 }