a38586d0865b6ce28e4b2c9ec94f80bc6b8ada10
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / methodbase.cs
1 // ==++==
2 // 
3 //   Copyright(c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 // 
8
9 namespace System.Reflection
10 {
11     using System;
12     using System.Diagnostics;
13     using System.Globalization;
14     using System.Runtime.CompilerServices;
15     using System.Runtime.InteropServices;
16     using System.Security.Permissions;
17     using System.Text;
18     using System.Threading;
19
20     //
21     // Invocation cached flags. Those are used in unmanaged code as well
22     // so be careful if you change them
23     //
24     [Flags]
25     internal enum INVOCATION_FLAGS : uint
26     {
27         INVOCATION_FLAGS_UNKNOWN = 0x00000000,
28         INVOCATION_FLAGS_INITIALIZED = 0x00000001,
29         // it's used for both method and field to signify that no access is allowed
30         INVOCATION_FLAGS_NO_INVOKE = 0x00000002,
31         INVOCATION_FLAGS_NEED_SECURITY = 0x00000004,
32         // Set for static ctors and ctors on abstract types, which
33         // can be invoked only if the "this" object is provided (even if it's null).
34         INVOCATION_FLAGS_NO_CTOR_INVOKE = 0x00000008,
35         // because field and method are different we can reuse the same bits
36         // method
37         INVOCATION_FLAGS_IS_CTOR = 0x00000010,
38         INVOCATION_FLAGS_RISKY_METHOD = 0x00000020,
39         INVOCATION_FLAGS_NON_W8P_FX_API = 0x00000040,
40         INVOCATION_FLAGS_IS_DELEGATE_CTOR = 0x00000080,
41         INVOCATION_FLAGS_CONTAINS_STACK_POINTERS = 0x00000100,
42         // field
43         INVOCATION_FLAGS_SPECIAL_FIELD = 0x00000010,
44         INVOCATION_FLAGS_FIELD_SPECIAL_CAST = 0x00000020,
45
46         // temporary flag used for flagging invocation of method vs ctor
47         // this flag never appears on the instance m_invocationFlag and is simply
48         // passed down from within ConstructorInfo.Invoke()
49         INVOCATION_FLAGS_CONSTRUCTOR_INVOKE = 0x10000000,
50     }
51
52     [Serializable]
53     [ClassInterface(ClassInterfaceType.None)]
54     [ComDefaultInterface(typeof(_MethodBase))]
55 #pragma warning disable 618
56     [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
57 #pragma warning restore 618
58     [System.Runtime.InteropServices.ComVisible(true)]
59     public abstract partial class MethodBase : MemberInfo, _MethodBase
60     {
61         #region Static Members
62         public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle)
63         {
64             if (handle.IsNullHandle())
65                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
66
67 #if MONO
68             MethodBase m = GetMethodFromHandleInternalType (handle.Value, IntPtr.Zero);
69             if (m == null)
70                 throw new ArgumentException ("The handle is invalid.");
71 #else
72             MethodBase m = RuntimeType.GetMethodBase(handle.GetMethodInfo());
73 #endif
74
75             Type declaringType = m.DeclaringType;
76             if (declaringType != null && declaringType.IsGenericType)
77                 throw new ArgumentException(String.Format(
78                     CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_MethodDeclaringTypeGeneric"), 
79                     m, declaringType.GetGenericTypeDefinition()));
80  
81             return m;
82         }
83
84         [System.Runtime.InteropServices.ComVisible(false)]
85         public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle, RuntimeTypeHandle declaringType)
86         {
87             if (handle.IsNullHandle())
88                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
89
90 #if MONO
91             MethodBase m = GetMethodFromHandleInternalType (handle.Value, declaringType.Value);
92             if (m == null)
93                 throw new ArgumentException ("The handle is invalid.");
94             return m;
95 #else
96             return RuntimeType.GetMethodBase(declaringType.GetRuntimeType(), handle.GetMethodInfo());
97 #endif
98         }
99
100 #if MONO
101         [MethodImplAttribute (MethodImplOptions.InternalCall)]
102         public extern static MethodBase GetCurrentMethod ();
103 #else
104         [System.Security.DynamicSecurityMethod] // Specify DynamicSecurityMethod attribute to prevent inlining of the caller.
105         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
106         public static MethodBase GetCurrentMethod()
107         {
108             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
109             return RuntimeMethodInfo.InternalGetCurrentMethod(ref stackMark);
110         }
111 #endif
112         #endregion
113
114         #region Constructor
115         protected MethodBase() { }
116         #endregion
117
118 #if !FEATURE_CORECLR
119         public static bool operator ==(MethodBase left, MethodBase right)
120         {
121             if (ReferenceEquals(left, right))
122                 return true;
123
124             if ((object)left == null || (object)right == null)
125                 return false;
126
127             MethodInfo method1, method2;
128             ConstructorInfo constructor1, constructor2;
129
130             if ((method1 = left as MethodInfo) != null && (method2 = right as MethodInfo) != null)
131                 return method1 == method2;
132             else if ((constructor1 = left as ConstructorInfo) != null && (constructor2 = right as ConstructorInfo) != null)
133                 return constructor1 == constructor2;
134
135             return false;
136         }
137
138         public static bool operator !=(MethodBase left, MethodBase right)
139         {
140             return !(left == right);
141         }
142 #endif // !FEATURE_CORECLR
143
144         public override bool Equals(object obj)
145         {
146             return base.Equals(obj);
147         }
148
149         public override int GetHashCode()
150         {
151             return base.GetHashCode();
152         }
153
154         #region Internal Members
155         // used by EE
156         [System.Security.SecurityCritical]
157         private IntPtr GetMethodDesc() { return MethodHandle.Value; }
158
159 #if FEATURE_APPX
160
161         // The C# dynamic and VB late bound binders need to call this API. Since we don't have time to make this
162         // public in Dev11, the C# and VB binders currently call this through a delegate. 
163         // When we make this API public (hopefully) in Dev12 we need to change the C# and VB binders to call this
164         // probably statically. The code is located in:
165         // C#: ndp\fx\src\CSharp\Microsoft\CSharp\SymbolTable.cs - Microsoft.CSharp.RuntimeBinder.SymbolTable..cctor
166         // VB: vb\runtime\msvbalib\helpers\Symbols.vb - Microsoft.VisualBasic.CompilerServices.Symbols..cctor
167         internal virtual bool IsDynamicallyInvokable
168         {
169             get
170             {
171                 return true;
172             }
173         }
174 #endif
175         #endregion
176
177         #region Public Abstract\Virtual Members
178         internal virtual ParameterInfo[] GetParametersNoCopy() { return GetParameters (); }
179
180         [System.Diagnostics.Contracts.Pure]
181         public abstract ParameterInfo[] GetParameters();
182
183         public virtual MethodImplAttributes MethodImplementationFlags
184         {
185             get
186             {
187                 return GetMethodImplementationFlags();
188             }
189         }
190
191         public abstract MethodImplAttributes GetMethodImplementationFlags();
192
193         public abstract RuntimeMethodHandle MethodHandle { get; }   
194
195         public abstract MethodAttributes Attributes  { get; }    
196
197         public abstract Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture);
198
199         public virtual CallingConventions CallingConvention { get { return CallingConventions.Standard; } }
200
201         [System.Runtime.InteropServices.ComVisible(true)]
202         public virtual Type[] GetGenericArguments() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
203         
204         public virtual bool IsGenericMethodDefinition { get { return false; } }
205
206         public virtual bool ContainsGenericParameters { get { return false; } }
207
208         public virtual bool IsGenericMethod { get { return false; } }
209
210         public virtual bool IsSecurityCritical { get { throw new NotImplementedException(); } }
211
212         public virtual bool IsSecuritySafeCritical { get { throw new NotImplementedException(); } }
213
214         public virtual bool IsSecurityTransparent { get { throw new NotImplementedException(); } }
215
216         #endregion
217
218         #region Public Members
219         [DebuggerStepThroughAttribute]
220         [Diagnostics.DebuggerHidden]
221         public Object Invoke(Object obj, Object[] parameters)
222         {
223             // Theoretically we should set up a LookForMyCaller stack mark here and pass that along.
224             // But to maintain backward compatibility we can't switch to calling an 
225             // internal overload that takes a stack mark.
226             // Fortunately the stack walker skips all the reflection invocation frames including this one.
227             // So this method will never be returned by the stack walker as the caller.
228             // See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp.
229             return Invoke(obj, BindingFlags.Default, null, parameters, null);
230         }
231
232         public bool IsPublic  { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; } }
233
234         public bool IsPrivate { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; } }
235
236         public bool IsFamily { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; } }
237
238         public bool IsAssembly { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly; } }
239
240         public bool IsFamilyAndAssembly { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; } }
241
242         public bool IsFamilyOrAssembly { get {return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; } }
243
244         public bool IsStatic { get { return(Attributes & MethodAttributes.Static) != 0; } }
245
246         public bool IsFinal { get { return(Attributes & MethodAttributes.Final) != 0; }
247         }
248         public bool IsVirtual { get { return(Attributes & MethodAttributes.Virtual) != 0; }
249         }   
250         public bool IsHideBySig { get { return(Attributes & MethodAttributes.HideBySig) != 0; } }  
251
252         public bool IsAbstract { get { return(Attributes & MethodAttributes.Abstract) != 0; } }
253
254         public bool IsSpecialName { get { return(Attributes & MethodAttributes.SpecialName) != 0; } }
255
256         [System.Runtime.InteropServices.ComVisible(true)]
257         public bool IsConstructor 
258         {
259             get 
260             {
261                 // To be backward compatible we only return true for instance RTSpecialName ctors.
262                 return (this is ConstructorInfo &&
263                         !IsStatic &&
264                         ((Attributes & MethodAttributes.RTSpecialName) == MethodAttributes.RTSpecialName));
265             }
266         }
267
268         [System.Security.SecuritySafeCritical]
269 #pragma warning disable 618
270         [ReflectionPermissionAttribute(SecurityAction.Demand, Flags=ReflectionPermissionFlag.MemberAccess)]            
271 #pragma warning restore 618
272         public virtual MethodBody GetMethodBody()
273         {
274             throw new InvalidOperationException();
275         }        
276         #endregion
277         
278         #region Internal Methods
279         // helper method to construct the string representation of the parameter list
280         // 
281
282         internal static string ConstructParameters(Type[] parameterTypes, CallingConventions callingConvention, bool serialization)
283         {
284             StringBuilder sbParamList = new StringBuilder();
285             string comma = "";
286
287             for (int i = 0; i < parameterTypes.Length; i++)
288             {
289                 Type t = parameterTypes[i];
290
291                 sbParamList.Append(comma);
292
293                 string typeName = t.FormatTypeName(serialization);
294
295                 // Legacy: Why use "ByRef" for by ref parameters? What language is this? 
296                 // VB uses "ByRef" but it should precede (not follow) the parameter name.
297                 // Why don't we just use "&"?
298                 if (t.IsByRef && !serialization)
299                 {
300                     sbParamList.Append(typeName.TrimEnd(new char[] { '&' }));
301                     sbParamList.Append(" ByRef");
302                 }
303                 else
304                 {
305                     sbParamList.Append(typeName);
306                 }
307
308                 comma = ", ";
309             }
310
311             if ((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
312             {
313                 sbParamList.Append(comma);
314                 sbParamList.Append("...");
315             }
316
317             return sbParamList.ToString();
318         }
319
320         internal string FullName
321         {
322             get
323             {
324                 return String.Format("{0}.{1}", DeclaringType.FullName, FormatNameAndSig());
325             }
326         }
327         internal string FormatNameAndSig()
328         {
329             return FormatNameAndSig(false);
330         }
331
332         internal virtual string FormatNameAndSig(bool serialization)
333         {
334             // Serialization uses ToString to resolve MethodInfo overloads.
335             StringBuilder sbName = new StringBuilder(Name);
336
337             sbName.Append("(");
338             sbName.Append(ConstructParameters(GetParameterTypes(), CallingConvention, serialization));
339             sbName.Append(")");
340
341             return sbName.ToString();
342         }
343
344         internal virtual Type[] GetParameterTypes()
345         {
346             ParameterInfo[] paramInfo = GetParametersNoCopy();
347
348             Type[] parameterTypes = new Type[paramInfo.Length];
349             for (int i = 0; i < paramInfo.Length; i++)
350                 parameterTypes[i] = paramInfo[i].ParameterType;
351
352             return parameterTypes;
353         }
354 #if !MONO
355         [System.Security.SecuritySafeCritical]
356         internal Object[] CheckArguments(Object[] parameters, Binder binder, 
357             BindingFlags invokeAttr, CultureInfo culture, Signature sig)
358         {
359             // copy the arguments in a different array so we detach from any user changes 
360             Object[] copyOfParameters = new Object[parameters.Length];
361             
362             ParameterInfo[] p = null;
363             for (int i = 0; i < parameters.Length; i++)
364             {
365                 Object arg = parameters[i];
366                 RuntimeType argRT = sig.Arguments[i];
367                 
368                 if (arg == Type.Missing)
369                 {
370                     if (p == null) 
371                         p = GetParametersNoCopy();
372                     if (p[i].DefaultValue == System.DBNull.Value)
373                         throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters");
374                     arg = p[i].DefaultValue;
375                 }
376                 copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr);
377             }
378
379             return copyOfParameters;
380         }
381 #endif
382         #endregion
383
384         #region _MethodBase Implementation
385 #if !FEATURE_CORECLR
386         Type _MethodBase.GetType() { return base.GetType(); }
387         bool _MethodBase.IsPublic { get { return IsPublic; } }
388         bool _MethodBase.IsPrivate { get { return IsPrivate; } }
389         bool _MethodBase.IsFamily { get { return IsFamily; } }
390         bool _MethodBase.IsAssembly { get { return IsAssembly; } }
391         bool _MethodBase.IsFamilyAndAssembly { get { return IsFamilyAndAssembly; } }
392         bool _MethodBase.IsFamilyOrAssembly { get { return IsFamilyOrAssembly; } }
393         bool _MethodBase.IsStatic { get { return IsStatic; } }
394         bool _MethodBase.IsFinal { get { return IsFinal; } }
395         bool _MethodBase.IsVirtual { get { return IsVirtual; } }
396         bool _MethodBase.IsHideBySig { get { return IsHideBySig; } }
397         bool _MethodBase.IsAbstract { get { return IsAbstract; } }
398         bool _MethodBase.IsSpecialName { get { return IsSpecialName; } }
399         bool _MethodBase.IsConstructor { get { return IsConstructor; } }
400
401         void _MethodBase.GetTypeInfoCount(out uint pcTInfo)
402         {
403             throw new NotImplementedException();
404         }
405
406         void _MethodBase.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
407         {
408             throw new NotImplementedException();
409         }
410
411         void _MethodBase.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
412         {
413             throw new NotImplementedException();
414         }
415
416         // If you implement this method, make sure to include _MethodBase.Invoke in VM\DangerousAPIs.h and 
417         // include _MethodBase in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
418         void _MethodBase.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
419         {
420             throw new NotImplementedException();
421         }
422 #endif
423         #endregion
424     }
425
426 }