* **/*: Flush. (Updates to sync with DbLinq r1020, adding additional
[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, MemberInfo member);
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 #pragma warning disable 649
69                 internal IntPtr mhandle;
70                 string name;
71                 Type reftype;
72 #pragma warning restore 649
73
74                 internal MonoMethod () {
75                 }
76
77                 internal MonoMethod (RuntimeMethodHandle mhandle) {
78                         this.mhandle = mhandle.Value;
79                 }
80                 
81                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
82                 internal static extern string get_name (MethodBase method);
83
84                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
85                 internal static extern MonoMethod get_base_definition (MonoMethod method);
86
87                 public override MethodInfo GetBaseDefinition ()
88                 {
89                         return get_base_definition (this);
90                 }
91
92 #if NET_2_0 || BOOTSTRAP_NET_2_0
93                 public override ParameterInfo ReturnParameter {
94                         get {
95                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
96                         }
97                 }
98 #endif
99
100                 public override Type ReturnType {
101                         get {
102                                 MonoMethodInfo info;
103                                 MonoMethodInfo.get_method_info (mhandle, out info);
104                                 return info.ret;
105                         }
106                 }
107                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
108                         get {
109                                 return new ParameterInfo (ReturnType, this, MonoMethodInfo.get_retval_marshal (mhandle));
110                         }
111                 }
112                 
113                 public override MethodImplAttributes GetMethodImplementationFlags() {
114                         MonoMethodInfo info;
115                         MonoMethodInfo.get_method_info (mhandle, out info);
116                         return info.iattrs;
117                 }
118
119                 public override ParameterInfo[] GetParameters() {
120                         return MonoMethodInfo.get_parameter_info (mhandle, this);
121                 }
122
123                 /*
124                  * InternalInvoke() receives the parameters correctly converted by the 
125                  * binder to match the types of the method signature.
126                  */
127                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
128                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
129
130                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
131                 {
132                         if (binder == null)
133                                 binder = Binder.DefaultBinder;
134                         ParameterInfo[] pinfo = GetParameters ();
135
136                         if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
137                                 throw new TargetParameterCountException ("parameters do not match signature");
138                         
139                         if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
140                                 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
141                                         throw new ArgumentException ("failed to convert parameters");
142                         } else {
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");
146                         }
147
148 #if !NET_2_1
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);
154                         }
155 #endif
156
157 #if NET_2_0
158                         if (ContainsGenericParameters)
159                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
160 #endif
161
162                         Exception exc;
163                         object o = null;
164
165                         try {
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);
170 #if NET_2_0
171                         } catch (ThreadAbortException) {
172                                 throw;
173 #endif
174 #if NET_2_1
175                         } catch (MethodAccessException) {
176                                 throw;
177 #endif
178                         } catch (Exception e) {
179                                 throw new TargetInvocationException (e);
180                         }
181
182                         if (exc != null)
183                                 throw exc;
184                         return o;
185                 }
186
187                 public override RuntimeMethodHandle MethodHandle { 
188                         get {return new RuntimeMethodHandle (mhandle);} 
189                 }
190                 public override MethodAttributes Attributes { 
191                         get {
192                                 MonoMethodInfo info;
193                                 MonoMethodInfo.get_method_info (mhandle, out info);
194                                 return info.attrs;
195                         } 
196                 }
197
198                 public override CallingConventions CallingConvention { 
199                         get {
200                                 MonoMethodInfo info;
201                                 MonoMethodInfo.get_method_info (mhandle, out info);
202                                 return info.callconv;
203                         }
204                 }
205                 
206                 public override Type ReflectedType {
207                         get {
208                                 return reftype;
209                         }
210                 }
211                 public override Type DeclaringType {
212                         get {
213                                 MonoMethodInfo info;
214                                 MonoMethodInfo.get_method_info (mhandle, out info);
215                                 return info.parent;
216                         }
217                 }
218                 public override string Name {
219                         get {
220                                 if (name != null)
221                                         return name;
222                                 return get_name (this);
223                         }
224                 }
225                 
226                 public override bool IsDefined (Type attributeType, bool inherit) {
227                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
228                 }
229
230                 public override object[] GetCustomAttributes( bool inherit) {
231                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
232                 }
233                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
234                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
235                 }
236
237                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
238                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
239
240                 internal object[] GetPseudoCustomAttributes ()
241                 {
242                         int count = 0;
243
244                         /* MS.NET doesn't report MethodImplAttribute */
245
246                         MonoMethodInfo info;
247                         MonoMethodInfo.get_method_info (mhandle, out info);
248                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
249                                 count ++;
250                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
251                                 count ++;
252                         
253                         if (count == 0)
254                                 return null;
255                         object[] attrs = new object [count];
256                         count = 0;
257
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;
265                         }
266
267                         return attrs;
268                 }
269
270                 static bool ShouldPrintFullName (Type type) {
271                         return type.IsClass && (!type.IsPointer ||
272 #if NET_2_0
273                                 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
274 #else
275                                 !type.GetElementType ().IsPrimitive);
276 #endif
277                 }
278
279                 public override string ToString () {
280                         StringBuilder sb = new StringBuilder ();
281                         Type retType = ReturnType;
282                         if (ShouldPrintFullName (retType))
283                                 sb.Append (retType.ToString ());
284                         else
285                                 sb.Append (retType.Name);
286                         sb.Append (" ");
287                         sb.Append (Name);
288 #if NET_2_0 || BOOTSTRAP_NET_2_0
289                         if (IsGenericMethod) {
290                                 Type[] gen_params = GetGenericArguments ();
291                                 sb.Append ("[");
292                                 for (int j = 0; j < gen_params.Length; j++) {
293                                         if (j > 0)
294                                                 sb.Append (",");
295                                         sb.Append (gen_params [j].Name);
296                                 }
297                                 sb.Append ("]");
298                         }
299 #endif
300                         sb.Append ("(");
301                         ParameterInfo[] p = GetParameters ();
302                         for (int i = 0; i < p.Length; ++i) {
303                                 if (i > 0)
304                                         sb.Append (", ");
305                                 Type pt = p[i].ParameterType;
306                                 bool byref = pt.IsByRef;
307                                 if (byref)
308                                         pt = pt.GetElementType ();
309                                 if (ShouldPrintFullName (pt))
310                                         sb.Append (pt.ToString ());
311                                 else
312                                         sb.Append (pt.Name);
313                                 if (byref)
314                                         sb.Append (" ByRef");
315                         }
316                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
317                                 if (p.Length > 0)
318                                         sb.Append (", ");
319                                 sb.Append ("...");
320                         }
321                         
322                         sb.Append (")");
323                         return sb.ToString ();
324                 }
325
326         
327                 // ISerializable
328                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
329                 {
330 #if NET_2_0
331                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
332                                 ? GetGenericArguments () : null;
333                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
334 #else
335                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method);
336 #endif
337                 }
338
339 #if NET_2_0 || BOOTSTRAP_NET_2_0
340                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
341                 {
342                         if (methodInstantiation == null)
343                                 throw new ArgumentNullException ("methodInstantiation");
344                         foreach (Type type in methodInstantiation)
345                                 if (type == null)
346                                         throw new ArgumentNullException ();
347
348                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
349                         if (ret == null)
350                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
351                         return ret;
352                 }
353
354                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
355                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
356
357                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
358                 public override extern Type [] GetGenericArguments ();
359
360                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
361                 extern MethodInfo GetGenericMethodDefinition_impl ();
362
363                 public override MethodInfo GetGenericMethodDefinition ()
364                 {
365                         MethodInfo res = GetGenericMethodDefinition_impl ();
366                         if (res == null)
367                                 throw new InvalidOperationException ();
368
369                         return res;
370                 }
371
372                 public override extern bool IsGenericMethodDefinition {
373                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
374                         get;
375                 }
376
377                 public override extern bool IsGenericMethod {
378                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
379                         get;
380                 }
381
382                 public override bool ContainsGenericParameters {
383                         get {
384                                 if (IsGenericMethod) {
385                                         foreach (Type arg in GetGenericArguments ())
386                                                 if (arg.ContainsGenericParameters)
387                                                         return true;
388                                 }
389                                 return DeclaringType.ContainsGenericParameters;
390                         }
391                 }
392 #endif
393
394 #if NET_2_0
395                 public override MethodBody GetMethodBody () {
396                         return GetMethodBody (mhandle);
397                 }
398 #endif
399         }
400         
401         internal class MonoCMethod : ConstructorInfo, ISerializable
402         {
403 #pragma warning disable 649             
404                 internal IntPtr mhandle;
405                 string name;
406                 Type reftype;
407 #pragma warning restore 649             
408                 
409                 public override MethodImplAttributes GetMethodImplementationFlags() {
410                         MonoMethodInfo info;
411                         MonoMethodInfo.get_method_info (mhandle, out info);
412                         return info.iattrs;
413                 }
414
415                 public override ParameterInfo[] GetParameters() {
416                         return MonoMethodInfo.get_parameter_info (mhandle, this);
417                 }
418
419                 /*
420                  * InternalInvoke() receives the parameters corretcly converted by the binder
421                  * to match the types of the method signature.
422                  */
423                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
424                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
425
426                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
427                 {
428                         if (binder == null)
429                                 binder = Binder.DefaultBinder;
430
431                         ParameterInfo[] pinfo = GetParameters ();
432
433                         if ((parameters == null && pinfo.Length != 0) || (parameters != null && parameters.Length != pinfo.Length))
434                                 throw new TargetParameterCountException ("parameters do not match signature");
435                         
436                         if ((invokeAttr & BindingFlags.ExactBinding) == 0) {
437                                 if (!Binder.ConvertArgs (binder, parameters, pinfo, culture))
438                                         throw new ArgumentException ("failed to convert parameters");
439                         } else {
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");
443                         }
444
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);
450                         }
451
452 #if NET_2_0
453                         if (obj == null && DeclaringType.ContainsGenericParameters)
454                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
455 #endif
456
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));
459                         }
460
461                         Exception exc = null;
462                         object o = null;
463
464                         try {
465                                 o = InternalInvoke (obj, parameters, out exc);
466 #if NET_2_1
467                         } catch (MethodAccessException) {
468                                 throw;
469 #endif
470                         } catch (Exception e) {
471                                 throw new TargetInvocationException (e);
472                         }
473
474                         if (exc != null)
475                                 throw exc;
476                         return (obj == null) ? o : null;
477                 }
478
479                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
480                         return Invoke (null, invokeAttr, binder, parameters, culture);
481                 }
482
483                 public override RuntimeMethodHandle MethodHandle { 
484                         get {return new RuntimeMethodHandle (mhandle);} 
485                 }
486                 public override MethodAttributes Attributes { 
487                         get {
488                                 MonoMethodInfo info;
489                                 MonoMethodInfo.get_method_info (mhandle, out info);
490                                 return info.attrs;
491                         } 
492                 }
493
494                 public override CallingConventions CallingConvention { 
495                         get {
496                                 MonoMethodInfo info;
497                                 MonoMethodInfo.get_method_info (mhandle, out info);
498                                 return info.callconv;
499                         }
500                 }
501                 
502                 public override Type ReflectedType {
503                         get {
504                                 return reftype;
505                         }
506                 }
507                 public override Type DeclaringType {
508                         get {
509                                 MonoMethodInfo info;
510                                 MonoMethodInfo.get_method_info (mhandle, out info);
511                                 return info.parent;
512                         }
513                 }
514                 public override string Name {
515                         get {
516                                 if (name != null)
517                                         return name;
518                                 return MonoMethod.get_name (this);
519                         }
520                 }
521
522                 public override bool IsDefined (Type attributeType, bool inherit) {
523                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
524                 }
525
526                 public override object[] GetCustomAttributes( bool inherit) {
527                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
528                 }
529
530                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
531                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
532                 }
533
534 #if NET_2_0
535                 public override MethodBody GetMethodBody () {
536                         return GetMethodBody (mhandle);
537                 }
538 #endif
539
540                 public override string ToString () {
541                         StringBuilder sb = new StringBuilder ();
542                         sb.Append ("Void ");
543                         sb.Append (Name);
544                         sb.Append ("(");
545                         ParameterInfo[] p = GetParameters ();
546                         for (int i = 0; i < p.Length; ++i) {
547                                 if (i > 0)
548                                         sb.Append (", ");
549                                 sb.Append (p[i].ParameterType.Name);
550                         }
551                         sb.Append (")");
552                         return sb.ToString ();
553                 }
554
555                 // ISerializable
556                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
557                 {
558                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
559                 }
560         }
561 }