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