Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / methodinfo.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.Collections.Generic;
13     using System.Diagnostics;
14     using System.Diagnostics.Contracts;
15     using System.Globalization;
16     using System.Runtime;
17     using System.Runtime.InteropServices;
18     using System.Runtime.ConstrainedExecution;
19 #if FEATURE_REMOTING
20     using System.Runtime.Remoting.Metadata;
21 #endif //FEATURE_REMOTING
22     using System.Runtime.Serialization;
23     using System.Security;
24     using System.Security.Permissions;
25     using System.Text;
26     using System.Threading;
27     using MemberListType = System.RuntimeType.MemberListType;
28 #if !MONO
29     using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
30 #endif
31     using System.Runtime.CompilerServices;
32
33     [Serializable]
34     [ClassInterface(ClassInterfaceType.None)]
35     [ComDefaultInterface(typeof(_MethodInfo))]
36 #pragma warning disable 618
37     [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
38 #pragma warning restore 618
39     [System.Runtime.InteropServices.ComVisible(true)]
40     public abstract class MethodInfo : MethodBase
41 #if !MOBILE
42     , _MethodInfo
43 #endif
44     {
45         #region Constructor
46         protected MethodInfo() { }
47         #endregion
48
49 #if !FEATURE_CORECLR
50         public static bool operator ==(MethodInfo left, MethodInfo right)
51         {
52             if (ReferenceEquals(left, right))
53                 return true;
54
55             if ((object)left == null || (object)right == null ||
56                 left is RuntimeMethodInfo || right is RuntimeMethodInfo)
57             {
58                 return false;
59             }
60             return left.Equals(right);
61         }
62
63         public static bool operator !=(MethodInfo left, MethodInfo right)
64         {
65             return !(left == right);
66         }
67 #endif // !FEATURE_CORECLR
68
69         public override bool Equals(object obj)
70         {
71             return base.Equals(obj);
72         }
73
74         public override int GetHashCode()
75         {
76             return base.GetHashCode();
77         }
78
79         #region MemberInfo Overrides
80         public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Method; } }
81         #endregion
82     
83         #region Public Abstract\Virtual Members
84         public virtual Type ReturnType { get { throw new NotImplementedException(); } }
85     
86         public virtual ParameterInfo ReturnParameter { get { throw new NotImplementedException(); } }
87
88         public abstract ICustomAttributeProvider ReturnTypeCustomAttributes { get;  }
89
90         public abstract MethodInfo GetBaseDefinition();
91
92         [System.Runtime.InteropServices.ComVisible(true)]
93         public override Type[] GetGenericArguments() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
94
95         [System.Runtime.InteropServices.ComVisible(true)]
96         public virtual MethodInfo GetGenericMethodDefinition() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
97
98         public virtual MethodInfo MakeGenericMethod(params Type[] typeArguments) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
99
100         public virtual Delegate CreateDelegate(Type delegateType) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
101         public virtual Delegate CreateDelegate(Type delegateType, Object target) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
102         #endregion
103
104 #if !FEATURE_CORECLR && !MOBILE
105         Type _MethodInfo.GetType()
106         {
107             return base.GetType();
108         }
109
110         void _MethodInfo.GetTypeInfoCount(out uint pcTInfo)
111         {
112             throw new NotImplementedException();
113         }
114
115         void _MethodInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
116         {
117             throw new NotImplementedException();
118         }
119
120         void _MethodInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
121         {
122             throw new NotImplementedException();
123         }
124
125         // If you implement this method, make sure to include _MethodInfo.Invoke in VM\DangerousAPIs.h and 
126         // include _MethodInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
127         void _MethodInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
128         {
129             throw new NotImplementedException();
130         }
131 #endif
132
133 #if MONO
134         // TODO: Remove, needed only for MonoCustomAttribute
135         internal virtual MethodInfo GetBaseMethod ()
136         {
137             return this;
138         }
139 #endif
140     }
141
142 #if !MONO
143     [Serializable]
144     internal sealed class RuntimeMethodInfo : MethodInfo, ISerializable, IRuntimeMethodInfo
145     {
146         #region Private Data Members
147         private IntPtr m_handle;        
148         private RuntimeTypeCache m_reflectedTypeCache;
149         private string m_name;
150         private string m_toString;
151         private ParameterInfo[] m_parameters;
152         private ParameterInfo m_returnParameter;
153         private BindingFlags m_bindingFlags;
154         private MethodAttributes m_methodAttributes;
155         private Signature m_signature;
156         private RuntimeType m_declaringType;
157         private object m_keepalive;
158         private INVOCATION_FLAGS m_invocationFlags;
159
160 #if FEATURE_APPX
161         private bool IsNonW8PFrameworkAPI()
162         {
163             if (m_declaringType.IsArray && IsPublic && !IsStatic)
164                 return false;
165
166             RuntimeAssembly rtAssembly = GetRuntimeAssembly();
167             if (rtAssembly.IsFrameworkAssembly())
168             {
169                 int ctorToken = rtAssembly.InvocableAttributeCtorToken;
170                 if (System.Reflection.MetadataToken.IsNullToken(ctorToken) ||
171                     !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken))
172                     return true;
173             }
174
175             if (GetRuntimeType().IsNonW8PFrameworkAPI())
176                 return true;
177
178             if (IsGenericMethod && !IsGenericMethodDefinition)
179             {
180                 foreach (Type t in GetGenericArguments())
181                 {
182                     if (((RuntimeType)t).IsNonW8PFrameworkAPI())
183                         return true;
184                 }
185             }
186
187             return false;
188         }
189
190         internal override bool IsDynamicallyInvokable
191         {
192             get
193             {
194                 return !AppDomain.ProfileAPICheck || !IsNonW8PFrameworkAPI();
195             }
196         }
197 #endif
198
199         internal INVOCATION_FLAGS InvocationFlags
200         {
201             [System.Security.SecuritySafeCritical]
202             get
203             {
204                 if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
205                 {
206                     INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN;
207
208                     Type declaringType = DeclaringType;
209
210                     //
211                     // first take care of all the NO_INVOKE cases. 
212                     if (ContainsGenericParameters ||
213                          ReturnType.IsByRef ||
214                          (declaringType != null && declaringType.ContainsGenericParameters) ||
215                          ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) ||
216                          ((Attributes & MethodAttributes.RequireSecObject) == MethodAttributes.RequireSecObject))
217                     {
218                         // We don't need other flags if this method cannot be invoked
219                         invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE;
220                     }
221                     else
222                     {
223                         // this should be an invocable method, determine the other flags that participate in invocation
224                         invocationFlags = RuntimeMethodHandle.GetSecurityFlags(this);
225
226                         if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) == 0)
227                         {
228                             if ( (Attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public ||
229                                  (declaringType != null && declaringType.NeedsReflectionSecurityCheck) )
230                             {
231                                 // If method is non-public, or declaring type is not visible
232                                 invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
233                             }
234                             else if (IsGenericMethod)
235                             {
236                                 Type[] genericArguments = GetGenericArguments();
237
238                                 for (int i = 0; i < genericArguments.Length; i++)
239                                 {
240                                     if (genericArguments[i].NeedsReflectionSecurityCheck)
241                                     {
242                                         invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
243                                         break;
244                                     }
245                                 }
246                             }
247                         }
248                     }
249
250 #if FEATURE_APPX
251                     if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
252                         invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
253 #endif // FEATURE_APPX
254
255                     m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
256                 }
257
258                 return m_invocationFlags;
259             }
260         }
261         #endregion
262
263         #region Constructor
264         [System.Security.SecurityCritical]  // auto-generated
265         internal RuntimeMethodInfo(
266             RuntimeMethodHandleInternal handle, RuntimeType declaringType, 
267             RuntimeTypeCache reflectedTypeCache, MethodAttributes methodAttributes, BindingFlags bindingFlags, object keepalive)
268         {
269             Contract.Ensures(!m_handle.IsNull());
270
271             Contract.Assert(!handle.IsNullHandle());
272             Contract.Assert(methodAttributes == RuntimeMethodHandle.GetAttributes(handle));            
273
274             m_bindingFlags = bindingFlags;
275             m_declaringType = declaringType;
276             m_keepalive = keepalive;
277             m_handle = handle.Value;
278             m_reflectedTypeCache = reflectedTypeCache;
279             m_methodAttributes = methodAttributes;
280         }
281         #endregion
282
283 #if FEATURE_REMOTING
284         #region Legacy Remoting Cache
285         // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h.
286         // This member is currently being used by Remoting for caching remoting data. If you
287         // need to cache data here, talk to the Remoting team to work out a mechanism, so that
288         // both caching systems can happily work together.
289         private RemotingMethodCachedData m_cachedData;
290
291         internal RemotingMethodCachedData RemotingCache
292         {
293             get
294             {
295                 // This grabs an internal copy of m_cachedData and uses
296                 // that instead of looking at m_cachedData directly because
297                 // the cache may get cleared asynchronously.  This prevents
298                 // us from having to take a lock.
299                 RemotingMethodCachedData cache = m_cachedData;
300                 if (cache == null)
301                 {
302                     cache = new RemotingMethodCachedData(this);
303                     RemotingMethodCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
304                     if (ret != null)
305                         cache = ret;
306                 }
307                 return cache;
308             }
309         }
310         #endregion
311 #endif //FEATURE_REMOTING
312
313         #region Private Methods
314         RuntimeMethodHandleInternal IRuntimeMethodInfo.Value
315         {
316             [System.Security.SecuritySafeCritical]
317             get
318             {
319                 return new RuntimeMethodHandleInternal(m_handle);
320             }
321         }
322
323         private RuntimeType ReflectedTypeInternal
324         { 
325             get 
326             { 
327                 return m_reflectedTypeCache.GetRuntimeType(); 
328             } 
329         }
330
331         [System.Security.SecurityCritical]  // auto-generated
332         private ParameterInfo[] FetchNonReturnParameters()
333         {
334             if (m_parameters == null)
335                 m_parameters = RuntimeParameterInfo.GetParameters(this, this, Signature);
336
337             return m_parameters;
338         }
339
340         [System.Security.SecurityCritical]  // auto-generated
341         private ParameterInfo FetchReturnParameter()
342         {
343             if (m_returnParameter == null)
344                 m_returnParameter = RuntimeParameterInfo.GetReturnParameter(this, this, Signature);
345
346             return m_returnParameter;
347         }
348         #endregion
349
350         #region Internal Members
351         internal override string FormatNameAndSig(bool serialization)
352         {
353             // Serialization uses ToString to resolve MethodInfo overloads.
354             StringBuilder sbName = new StringBuilder(Name);
355
356             // serialization == true: use unambiguous (except for assembly name) type names to distinguish between overloads.
357             // serialization == false: use basic format to maintain backward compatibility of MethodInfo.ToString().
358             TypeNameFormatFlags format = serialization ? TypeNameFormatFlags.FormatSerialization : TypeNameFormatFlags.FormatBasic;
359
360             if (IsGenericMethod)
361                 sbName.Append(RuntimeMethodHandle.ConstructInstantiation(this, format));
362
363             sbName.Append("(");
364             sbName.Append(ConstructParameters(GetParameterTypes(), CallingConvention, serialization));
365             sbName.Append(")");
366
367             return sbName.ToString();
368         }
369
370         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
371         internal override bool CacheEquals(object o) 
372         { 
373             RuntimeMethodInfo m = o as RuntimeMethodInfo;
374
375             if ((object)m == null)
376                 return false;
377
378             return m.m_handle == m_handle;
379         } 
380
381         internal Signature Signature
382         {
383             get
384             {
385                 if (m_signature == null)
386                     m_signature = new Signature(this, m_declaringType);
387
388                 return m_signature;
389             }
390         }
391
392         internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
393
394         // Differs from MethodHandle in that it will return a valid handle even for reflection only loaded types
395         internal RuntimeMethodHandle GetMethodHandle()
396         {
397             return new RuntimeMethodHandle(this);
398         }
399
400         [System.Security.SecuritySafeCritical]  // auto-generated
401         internal RuntimeMethodInfo GetParentDefinition()
402         {
403             if (!IsVirtual || m_declaringType.IsInterface)
404                 return null;
405
406             RuntimeType parent = (RuntimeType)m_declaringType.BaseType;
407
408             if (parent == null)
409                 return null;
410
411             int slot = RuntimeMethodHandle.GetSlot(this);
412
413             if (RuntimeTypeHandle.GetNumVirtuals(parent) <= slot)
414                 return null;
415
416             return (RuntimeMethodInfo)RuntimeType.GetMethodBase(parent, RuntimeTypeHandle.GetMethodAt(parent, slot));
417         }
418
419         // Unlike DeclaringType, this will return a valid type even for global methods
420         internal RuntimeType GetDeclaringTypeInternal()
421         {
422             return m_declaringType;
423         }
424
425         #endregion
426
427         #region Object Overrides
428         public override String ToString() 
429         {
430             if (m_toString == null)
431                 m_toString = ReturnType.FormatTypeName() + " " + FormatNameAndSig();
432
433             return m_toString;
434         }
435
436         public override int GetHashCode()
437         {
438             // See RuntimeMethodInfo.Equals() below.
439             if (IsGenericMethod)
440                 return ValueType.GetHashCodeOfPtr(m_handle);
441             else
442                 return base.GetHashCode();
443         }
444
445         [System.Security.SecuritySafeCritical]  // auto-generated
446         public override bool Equals(object obj)
447         {
448             if (!IsGenericMethod)
449                 return obj == (object)this;
450
451             // We cannot do simple object identity comparisons for generic methods.
452             // Equals will be called in CerHashTable when RuntimeType+RuntimeTypeCache.GetGenericMethodInfo()
453             // retrive items from and insert items into s_methodInstantiations which is a CerHashtable.
454             // 
455
456             RuntimeMethodInfo mi = obj as RuntimeMethodInfo;
457
458             if (mi == null || !mi.IsGenericMethod)
459                 return false;
460
461             // now we know that both operands are generic methods
462
463             IRuntimeMethodInfo handle1 = RuntimeMethodHandle.StripMethodInstantiation(this);
464             IRuntimeMethodInfo handle2 = RuntimeMethodHandle.StripMethodInstantiation(mi);
465             if (handle1.Value.Value != handle2.Value.Value)
466                 return false;
467
468             Type[] lhs = GetGenericArguments();
469             Type[] rhs = mi.GetGenericArguments();
470
471             if (lhs.Length != rhs.Length)
472                 return false;
473
474             for (int i = 0; i < lhs.Length; i++)
475             {
476                 if (lhs[i] != rhs[i])
477                     return false;
478             }
479
480             if (DeclaringType != mi.DeclaringType)
481                 return false;
482
483             if (ReflectedType != mi.ReflectedType)
484                 return false;
485
486             return true;
487         }
488         #endregion
489
490         #region ICustomAttributeProvider
491         [System.Security.SecuritySafeCritical]  // auto-generated
492         public override Object[] GetCustomAttributes(bool inherit)
493         {
494             return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType as RuntimeType, inherit);
495         }
496
497         [System.Security.SecuritySafeCritical]  // auto-generated
498         public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
499         {
500             if (attributeType == null)
501                 throw new ArgumentNullException("attributeType");
502             Contract.EndContractBlock();
503
504             RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
505
506             if (attributeRuntimeType == null) 
507                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
508
509             return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit);
510         }
511
512         public override bool IsDefined(Type attributeType, bool inherit)
513         {
514             if (attributeType == null)
515                 throw new ArgumentNullException("attributeType");
516             Contract.EndContractBlock();
517
518             RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
519
520             if (attributeRuntimeType == null) 
521                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
522
523             return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit);
524         }
525
526         public override IList<CustomAttributeData> GetCustomAttributesData()
527         {
528             return CustomAttributeData.GetCustomAttributesInternal(this);
529         }
530         #endregion
531
532         #region MemberInfo Overrides
533         public override String Name 
534         {
535             [System.Security.SecuritySafeCritical]  // auto-generated
536             get
537             {
538                 if (m_name == null)
539                     m_name = RuntimeMethodHandle.GetName(this);
540
541                 return m_name;
542             }
543         }
544
545         public override Type DeclaringType 
546         {
547             get
548             {
549                 if (m_reflectedTypeCache.IsGlobal)
550                     return null;
551
552                 return m_declaringType;
553             }
554         }
555
556         public override Type ReflectedType 
557         {
558             get
559             {
560                 if (m_reflectedTypeCache.IsGlobal)
561                     return null;
562
563                 return m_reflectedTypeCache.GetRuntimeType();
564             }
565         }
566
567         public override MemberTypes MemberType { get { return MemberTypes.Method; } }
568         public override int MetadataToken
569         {
570             [System.Security.SecuritySafeCritical]  // auto-generated
571             get { return RuntimeMethodHandle.GetMethodDef(this); }
572         }        
573         public override Module Module { get { return GetRuntimeModule(); } }
574         internal RuntimeType GetRuntimeType() { return m_declaringType; }
575         internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
576         internal RuntimeAssembly GetRuntimeAssembly() { return GetRuntimeModule().GetRuntimeAssembly(); }
577
578         public override bool IsSecurityCritical 
579         {
580             get { return RuntimeMethodHandle.IsSecurityCritical(this); } 
581         }
582         public override bool IsSecuritySafeCritical
583         {
584             get { return RuntimeMethodHandle.IsSecuritySafeCritical(this); }
585         }
586         public override bool IsSecurityTransparent
587         {
588             get { return RuntimeMethodHandle.IsSecurityTransparent(this); }
589         }
590         #endregion
591
592         #region MethodBase Overrides
593         [System.Security.SecuritySafeCritical]  // auto-generated
594         internal override ParameterInfo[] GetParametersNoCopy()
595         {
596             FetchNonReturnParameters();
597
598             return m_parameters;
599         }
600
601         [System.Security.SecuritySafeCritical]  // auto-generated
602         [System.Diagnostics.Contracts.Pure]
603         public override ParameterInfo[] GetParameters()
604         {
605             FetchNonReturnParameters();
606
607             if (m_parameters.Length == 0)
608                 return m_parameters;
609
610             ParameterInfo[] ret = new ParameterInfo[m_parameters.Length];
611
612             Array.Copy(m_parameters, ret, m_parameters.Length);
613
614             return ret;
615         }
616
617         public override MethodImplAttributes GetMethodImplementationFlags()
618         {
619             return RuntimeMethodHandle.GetImplAttributes(this);
620         }
621
622         internal bool IsOverloaded
623         {
624             get 
625             {
626                 return m_reflectedTypeCache.GetMethodList(MemberListType.CaseSensitive, Name).Length > 1;
627             }
628         }
629
630         public override RuntimeMethodHandle MethodHandle 
631         { 
632             get 
633             { 
634                 Type declaringType = DeclaringType;
635                 if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
636                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
637                 return new RuntimeMethodHandle(this); 
638             } 
639         }
640
641         public override MethodAttributes Attributes { get { return m_methodAttributes; } }
642         
643         public override CallingConventions CallingConvention 
644         { 
645             get 
646             { 
647                 return Signature.CallingConvention; 
648             } 
649         }
650
651         [System.Security.SecuritySafeCritical] // overrides SafeCritical member
652 #if !FEATURE_CORECLR
653 #pragma warning disable 618
654         [ReflectionPermissionAttribute(SecurityAction.Demand, Flags = ReflectionPermissionFlag.MemberAccess)]
655 #pragma warning restore 618
656 #endif
657         public override MethodBody GetMethodBody()
658         {
659             MethodBody mb = RuntimeMethodHandle.GetMethodBody(this, ReflectedTypeInternal);
660             if (mb != null) 
661                 mb.m_methodBase = this;
662             return mb;
663         }        
664         #endregion
665
666         #region Invocation Logic(On MemberBase)
667         private void CheckConsistency(Object target) 
668         {
669             // only test instance methods
670             if ((m_methodAttributes & MethodAttributes.Static) != MethodAttributes.Static) 
671             {
672                 if (!m_declaringType.IsInstanceOfType(target))
673                 {
674                     if (target == null) 
675                         throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatMethReqTarg"));
676                     else
677                         throw new TargetException(Environment.GetResourceString("RFLCT.Targ_ITargMismatch"));
678                 }
679             }
680         }
681
682         [System.Security.SecuritySafeCritical]
683         private void ThrowNoInvokeException()
684         {
685             // method is ReflectionOnly
686             Type declaringType = DeclaringType;
687             if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
688             {
689                 throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyInvoke"));
690             }
691             // method is on a class that contains stack pointers
692             else if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS) != 0)
693             {
694                 throw new NotSupportedException();
695             }
696             // method is vararg
697             else if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
698             {
699                 throw new NotSupportedException();
700             }
701             // method is generic or on a generic class
702             else if (DeclaringType.ContainsGenericParameters || ContainsGenericParameters)
703             {
704                 throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenParam"));
705             }
706             // method is abstract class
707             else if (IsAbstract)
708             {
709                 throw new MemberAccessException();
710             }
711             // ByRef return are not allowed in reflection
712             else if (ReturnType.IsByRef)
713             {
714                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_ByRefReturn"));
715             }
716
717             throw new TargetException();
718         }
719         
720         [System.Security.SecuritySafeCritical]
721         [DebuggerStepThroughAttribute]
722         [Diagnostics.DebuggerHidden]
723         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
724         public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
725         {
726             object[] arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture);
727
728             #region Security Check
729             INVOCATION_FLAGS invocationFlags = InvocationFlags;
730
731 #if FEATURE_APPX
732             if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
733             {
734                 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
735                 RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
736                 if (caller != null && !caller.IsSafeForReflection())
737                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
738             }
739 #endif
740
741             if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0)
742             {
743 #if !FEATURE_CORECLR
744                 if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0)
745                     CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess);
746
747                 if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0)
748 #endif // !FEATURE_CORECLR
749                     RuntimeMethodHandle.PerformSecurityCheck(obj, this, m_declaringType, (uint)m_invocationFlags);
750             }
751             #endregion
752
753             return UnsafeInvokeInternal(obj, parameters, arguments);
754         }
755
756         [System.Security.SecurityCritical]
757         [DebuggerStepThroughAttribute]
758         [Diagnostics.DebuggerHidden]
759         internal object UnsafeInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
760         {
761             object[] arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture);
762
763             return UnsafeInvokeInternal(obj, parameters, arguments);
764         }
765
766         [System.Security.SecurityCritical]
767         [DebuggerStepThroughAttribute]
768         [Diagnostics.DebuggerHidden]
769         private object UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
770         {
771             if (arguments == null || arguments.Length == 0)
772                 return RuntimeMethodHandle.InvokeMethod(obj, null, Signature, false);
773             else
774             {
775                 Object retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false);
776
777                 // copy out. This should be made only if ByRef are present.
778                 for (int index = 0; index < arguments.Length; index++)
779                     parameters[index] = arguments[index];
780
781                 return retValue;
782             }
783         }
784
785         [DebuggerStepThroughAttribute]
786         [Diagnostics.DebuggerHidden]
787         private object[] InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
788         {
789             Signature sig = Signature;
790
791             // get the signature 
792             int formalCount = sig.Arguments.Length;
793             int actualCount = (parameters != null) ? parameters.Length : 0;
794
795             INVOCATION_FLAGS invocationFlags = InvocationFlags;
796
797             // INVOCATION_FLAGS_CONTAINS_STACK_POINTERS means that the struct (either the declaring type or the return type)
798             // contains pointers that point to the stack. This is either a ByRef or a TypedReference. These structs cannot
799             // be boxed and thus cannot be invoked through reflection which only deals with boxed value type objects.
800             if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS)) != 0)
801                 ThrowNoInvokeException();
802
803             // check basic method consistency. This call will throw if there are problems in the target/method relationship
804             CheckConsistency(obj);
805
806             if (formalCount != actualCount)
807                 throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt"));
808
809             if (actualCount != 0)
810                 return CheckArguments(parameters, binder, invokeAttr, culture, sig);
811             else
812                 return null;
813         }
814
815         #endregion
816
817         #region MethodInfo Overrides
818         public override Type ReturnType 
819         { 
820             get { return Signature.ReturnType; } 
821         }
822
823         public override ICustomAttributeProvider ReturnTypeCustomAttributes 
824         { 
825             get { return ReturnParameter; } 
826         }
827
828         public override ParameterInfo ReturnParameter 
829         {
830             [System.Security.SecuritySafeCritical]  // auto-generated
831             get
832             {
833                 Contract.Ensures(m_returnParameter != null);
834
835                 FetchReturnParameter();
836                 return m_returnParameter as ParameterInfo;
837             }
838         }
839
840         [System.Security.SecuritySafeCritical]  // auto-generated
841         public override MethodInfo GetBaseDefinition()
842         {
843             if (!IsVirtual || IsStatic || m_declaringType == null || m_declaringType.IsInterface)
844                 return this;
845
846             int slot = RuntimeMethodHandle.GetSlot(this);
847             RuntimeType declaringType = (RuntimeType)DeclaringType;
848             RuntimeType baseDeclaringType = declaringType;
849             RuntimeMethodHandleInternal baseMethodHandle = new RuntimeMethodHandleInternal();
850
851             do {
852                 int cVtblSlots = RuntimeTypeHandle.GetNumVirtuals(declaringType);
853
854                 if (cVtblSlots <= slot)
855                     break;
856
857                 baseMethodHandle = RuntimeTypeHandle.GetMethodAt(declaringType, slot);
858                 baseDeclaringType = declaringType;
859
860                 declaringType = (RuntimeType)declaringType.BaseType;
861             } while (declaringType != null);
862
863             return(MethodInfo)RuntimeType.GetMethodBase(baseDeclaringType, baseMethodHandle);
864         }
865
866         [System.Security.SecuritySafeCritical]
867         public override Delegate CreateDelegate(Type delegateType)
868         {
869             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
870
871             // This API existed in v1/v1.1 and only expected to create closed
872             // instance delegates. Constrain the call to BindToMethodInfo to
873             // open delegates only for backwards compatibility. But we'll allow
874             // relaxed signature checking and open static delegates because
875             // there's no ambiguity there (the caller would have to explicitly
876             // pass us a static method or a method with a non-exact signature
877             // and the only change in behavior from v1.1 there is that we won't
878             // fail the call).
879             return CreateDelegateInternal(
880                 delegateType,
881                 null,
882                 DelegateBindingFlags.OpenDelegateOnly | DelegateBindingFlags.RelaxedSignature,
883                 ref stackMark);
884         }
885
886         [System.Security.SecuritySafeCritical]
887         public override Delegate CreateDelegate(Type delegateType, Object target)
888         {
889             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
890
891             // This API is new in Whidbey and allows the full range of delegate
892             // flexability (open or closed delegates binding to static or
893             // instance methods with relaxed signature checking). The delegate
894             // can also be closed over null. There's no ambiguity with all these
895             // options since the caller is providing us a specific MethodInfo.
896             return CreateDelegateInternal(
897                 delegateType,
898                 target,
899                 DelegateBindingFlags.RelaxedSignature,
900                 ref stackMark);
901         }
902
903         [System.Security.SecurityCritical]
904         private Delegate CreateDelegateInternal(Type delegateType, Object firstArgument, DelegateBindingFlags bindingFlags, ref StackCrawlMark stackMark)
905         {
906             // Validate the parameters.
907             if (delegateType == null)
908                 throw new ArgumentNullException("delegateType");
909             Contract.EndContractBlock();
910
911             RuntimeType rtType = delegateType as RuntimeType;
912             if (rtType == null)
913                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "delegateType");
914
915             if (!rtType.IsDelegate())
916                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "delegateType");
917
918             Delegate d = Delegate.CreateDelegateInternal(rtType, this, firstArgument, bindingFlags, ref stackMark);
919             if (d == null)
920             {
921                 throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
922             }
923
924             return d;
925         }
926
927         #endregion
928
929         #region Generics
930         [System.Security.SecuritySafeCritical]  // auto-generated
931         public override MethodInfo MakeGenericMethod(params Type[] methodInstantiation)
932         {
933           if (methodInstantiation == null)
934                 throw new ArgumentNullException("methodInstantiation");
935           Contract.EndContractBlock();
936
937             RuntimeType[] methodInstantionRuntimeType = new RuntimeType[methodInstantiation.Length];
938
939             if (!IsGenericMethodDefinition)
940                 throw new InvalidOperationException(
941                     Environment.GetResourceString("Arg_NotGenericMethodDefinition", this));
942
943             for (int i = 0; i < methodInstantiation.Length; i++)
944             {
945                 Type methodInstantiationElem = methodInstantiation[i];
946
947                 if (methodInstantiationElem == null)
948                     throw new ArgumentNullException();
949
950                 RuntimeType rtMethodInstantiationElem = methodInstantiationElem as RuntimeType;
951
952                 if (rtMethodInstantiationElem == null)
953                 {
954                     Type[] methodInstantiationCopy = new Type[methodInstantiation.Length];
955                     for (int iCopy = 0; iCopy < methodInstantiation.Length; iCopy++)
956                         methodInstantiationCopy[iCopy] = methodInstantiation[iCopy];
957                     methodInstantiation = methodInstantiationCopy;
958                     return System.Reflection.Emit.MethodBuilderInstantiation.MakeGenericMethod(this, methodInstantiation);
959                 }
960
961                 methodInstantionRuntimeType[i] = rtMethodInstantiationElem;
962             }
963
964             RuntimeType[] genericParameters = GetGenericArgumentsInternal();
965
966             RuntimeType.SanityCheckGenericArguments(methodInstantionRuntimeType, genericParameters);
967
968             MethodInfo ret = null;
969                 
970             try
971             {
972                 ret = RuntimeType.GetMethodBase(ReflectedTypeInternal,
973                     RuntimeMethodHandle.GetStubIfNeeded(new RuntimeMethodHandleInternal(this.m_handle), m_declaringType, methodInstantionRuntimeType)) as MethodInfo;
974             }
975             catch (VerificationException e)
976             {
977                 RuntimeType.ValidateGenericArguments(this, methodInstantionRuntimeType, e);
978                 throw;
979             }
980             
981             return ret;
982         }
983
984         internal RuntimeType[] GetGenericArgumentsInternal()
985         {
986             return RuntimeMethodHandle.GetMethodInstantiationInternal(this);
987         }
988
989         public override Type[] GetGenericArguments() 
990         {
991             Type[] types = RuntimeMethodHandle.GetMethodInstantiationPublic(this);
992
993             if (types == null)
994             {
995                 types = EmptyArray<Type>.Value;
996             }
997             return types;
998         }
999
1000         public override MethodInfo GetGenericMethodDefinition() 
1001         {
1002             if (!IsGenericMethod)
1003                 throw new InvalidOperationException();
1004             Contract.EndContractBlock();
1005             
1006             return RuntimeType.GetMethodBase(m_declaringType, RuntimeMethodHandle.StripMethodInstantiation(this)) as MethodInfo;
1007         }
1008
1009         public override bool IsGenericMethod
1010         {
1011             get { return RuntimeMethodHandle.HasMethodInstantiation(this); }
1012         }
1013
1014         public override bool IsGenericMethodDefinition
1015         {
1016             get { return RuntimeMethodHandle.IsGenericMethodDefinition(this); }
1017         } 
1018
1019         public override bool ContainsGenericParameters 
1020         { 
1021             get 
1022             {
1023                 if (DeclaringType != null && DeclaringType.ContainsGenericParameters)
1024                     return true;
1025
1026                 if (!IsGenericMethod)
1027                     return false;
1028
1029                 Type[] pis = GetGenericArguments(); 
1030                 for (int i = 0; i < pis.Length; i++)
1031                 {
1032                     if (pis[i].ContainsGenericParameters)
1033                         return true;
1034                 }
1035
1036                 return false;
1037             } 
1038         }
1039         #endregion
1040
1041         #region ISerializable Implementation
1042         [System.Security.SecurityCritical]  // auto-generated
1043         public void GetObjectData(SerializationInfo info, StreamingContext context)
1044         {
1045             if (info == null)
1046                 throw new ArgumentNullException("info");
1047             Contract.EndContractBlock();
1048
1049             if (m_reflectedTypeCache.IsGlobal)
1050                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalMethodSerialization"));
1051
1052             MemberInfoSerializationHolder.GetSerializationInfo(
1053                 info,
1054                 Name,
1055                 ReflectedTypeInternal,
1056                 ToString(),
1057                 SerializationToString(),
1058                 MemberTypes.Method,
1059                 IsGenericMethod & !IsGenericMethodDefinition ? GetGenericArguments() : null);
1060         }
1061
1062         internal string SerializationToString()
1063         {
1064             return ReturnType.FormatTypeName(true) + " " + FormatNameAndSig(true);
1065         }
1066         #endregion
1067
1068         #region Legacy Internal
1069         internal static MethodBase InternalGetCurrentMethod(ref StackCrawlMark stackMark)
1070         {
1071             IRuntimeMethodInfo method = RuntimeMethodHandle.GetCurrentMethod(ref stackMark);
1072
1073             if (method == null) 
1074                 return null;
1075             
1076             return RuntimeType.GetMethodBase(method);
1077         }
1078         #endregion
1079     }
1080 #endif
1081 }