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