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