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