// ==++== // // Copyright(c) Microsoft Corporation. All rights reserved. // // ==--== // [....] // namespace System.Reflection { using System; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Text; using System.Threading; // // Invocation cached flags. Those are used in unmanaged code as well // so be careful if you change them // [Flags] internal enum INVOCATION_FLAGS : uint { INVOCATION_FLAGS_UNKNOWN = 0x00000000, INVOCATION_FLAGS_INITIALIZED = 0x00000001, // it's used for both method and field to signify that no access is allowed INVOCATION_FLAGS_NO_INVOKE = 0x00000002, INVOCATION_FLAGS_NEED_SECURITY = 0x00000004, // Set for static ctors and ctors on abstract types, which // can be invoked only if the "this" object is provided (even if it's null). INVOCATION_FLAGS_NO_CTOR_INVOKE = 0x00000008, // because field and method are different we can reuse the same bits // method INVOCATION_FLAGS_IS_CTOR = 0x00000010, INVOCATION_FLAGS_RISKY_METHOD = 0x00000020, INVOCATION_FLAGS_NON_W8P_FX_API = 0x00000040, INVOCATION_FLAGS_IS_DELEGATE_CTOR = 0x00000080, INVOCATION_FLAGS_CONTAINS_STACK_POINTERS = 0x00000100, // field INVOCATION_FLAGS_SPECIAL_FIELD = 0x00000010, INVOCATION_FLAGS_FIELD_SPECIAL_CAST = 0x00000020, // temporary flag used for flagging invocation of method vs ctor // this flag never appears on the instance m_invocationFlag and is simply // passed down from within ConstructorInfo.Invoke() INVOCATION_FLAGS_CONSTRUCTOR_INVOKE = 0x10000000, } [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_MethodBase))] #pragma warning disable 618 [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] #pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract partial class MethodBase : MemberInfo, _MethodBase { #region Static Members public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle) { if (handle.IsNullHandle()) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle")); #if !FEATURE_CORECLR && !MONO if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage)) { FrameworkEventSource.Log.BeginGetMethodFromHandle(); } #endif #if MONO MethodBase m = GetMethodFromHandleInternalType (handle.Value, IntPtr.Zero); if (m == null) throw new ArgumentException ("The handle is invalid."); #else MethodBase m = RuntimeType.GetMethodBase(handle.GetMethodInfo()); #endif Type declaringType = m.DeclaringType; #if !FEATURE_CORECLR && !MONO if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage) && declaringType != null) { FrameworkEventSource.Log.EndGetMethodFromHandle(declaringType.GetFullNameForEtw(), m.GetFullNameForEtw()); } #endif if (declaringType != null && declaringType.IsGenericType) throw new ArgumentException(String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_MethodDeclaringTypeGeneric"), m, declaringType.GetGenericTypeDefinition())); return m; } [System.Runtime.InteropServices.ComVisible(false)] public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle, RuntimeTypeHandle declaringType) { if (handle.IsNullHandle()) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle")); #if !FEATURE_CORECLR && !MONO if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage)) { FrameworkEventSource.Log.BeginGetMethodFromHandle(); } #endif #if MONO MethodBase m = GetMethodFromHandleInternalType (handle.Value, declaringType.Value); if (m == null) throw new ArgumentException ("The handle is invalid."); #else MethodBase m = RuntimeType.GetMethodBase(declaringType.GetRuntimeType(), handle.GetMethodInfo()); #endif #if !FEATURE_CORECLR && !MONO if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage) && declaringType != null && m != null) { FrameworkEventSource.Log.EndGetMethodFromHandle(declaringType.GetRuntimeType().GetFullNameForEtw(), m.GetFullNameForEtw()); } #endif return m; } #if MONO [MethodImplAttribute (MethodImplOptions.InternalCall)] public extern static MethodBase GetCurrentMethod (); #else [System.Security.DynamicSecurityMethod] // Specify DynamicSecurityMethod attribute to prevent inlining of the caller. [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static MethodBase GetCurrentMethod() { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RuntimeMethodInfo.InternalGetCurrentMethod(ref stackMark); } #endif #endregion #region Constructor protected MethodBase() { } #endregion #if !FEATURE_CORECLR public static bool operator ==(MethodBase left, MethodBase right) { if (ReferenceEquals(left, right)) return true; if ((object)left == null || (object)right == null) return false; MethodInfo method1, method2; ConstructorInfo constructor1, constructor2; if ((method1 = left as MethodInfo) != null && (method2 = right as MethodInfo) != null) return method1 == method2; else if ((constructor1 = left as ConstructorInfo) != null && (constructor2 = right as ConstructorInfo) != null) return constructor1 == constructor2; return false; } public static bool operator !=(MethodBase left, MethodBase right) { return !(left == right); } #endif // !FEATURE_CORECLR #if FEATURE_NETCORE || !FEATURE_CORECLR public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } #endif //FEATURE_NETCORE || !FEATURE_CORECLR #region Internal Members // used by EE [System.Security.SecurityCritical] private IntPtr GetMethodDesc() { return MethodHandle.Value; } #if FEATURE_APPX // The C# dynamic and VB late bound binders need to call this API. Since we don't have time to make this // public in Dev11, the C# and VB binders currently call this through a delegate. // When we make this API public (hopefully) in Dev12 we need to change the C# and VB binders to call this // probably statically. The code is located in: // C#: ndp\fx\src\CSharp\Microsoft\CSharp\SymbolTable.cs - Microsoft.CSharp.RuntimeBinder.SymbolTable..cctor // VB: vb\runtime\msvbalib\helpers\Symbols.vb - Microsoft.VisualBasic.CompilerServices.Symbols..cctor internal virtual bool IsDynamicallyInvokable { get { return true; } } #endif #endregion #region Public Abstract\Virtual Members internal virtual ParameterInfo[] GetParametersNoCopy() { return GetParameters (); } [System.Diagnostics.Contracts.Pure] public abstract ParameterInfo[] GetParameters(); public virtual MethodImplAttributes MethodImplementationFlags { get { return GetMethodImplementationFlags(); } } public abstract MethodImplAttributes GetMethodImplementationFlags(); public abstract RuntimeMethodHandle MethodHandle { get; } public abstract MethodAttributes Attributes { get; } public abstract Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture); public virtual CallingConventions CallingConvention { get { return CallingConventions.Standard; } } [System.Runtime.InteropServices.ComVisible(true)] public virtual Type[] GetGenericArguments() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } public virtual bool IsGenericMethodDefinition { get { return false; } } public virtual bool ContainsGenericParameters { get { return false; } } public virtual bool IsGenericMethod { get { return false; } } public virtual bool IsSecurityCritical { get { throw new NotImplementedException(); } } public virtual bool IsSecuritySafeCritical { get { throw new NotImplementedException(); } } public virtual bool IsSecurityTransparent { get { throw new NotImplementedException(); } } #endregion #region _MethodBase Implementation Type _MethodBase.GetType() { return base.GetType(); } bool _MethodBase.IsPublic { get { return IsPublic; } } bool _MethodBase.IsPrivate { get { return IsPrivate; } } bool _MethodBase.IsFamily { get { return IsFamily; } } bool _MethodBase.IsAssembly { get { return IsAssembly; } } bool _MethodBase.IsFamilyAndAssembly { get { return IsFamilyAndAssembly; } } bool _MethodBase.IsFamilyOrAssembly { get { return IsFamilyOrAssembly; } } bool _MethodBase.IsStatic { get { return IsStatic; } } bool _MethodBase.IsFinal { get { return IsFinal; } } bool _MethodBase.IsVirtual { get { return IsVirtual; } } bool _MethodBase.IsHideBySig { get { return IsHideBySig; } } bool _MethodBase.IsAbstract { get { return IsAbstract; } } bool _MethodBase.IsSpecialName { get { return IsSpecialName; } } bool _MethodBase.IsConstructor { get { return IsConstructor; } } #endregion #region Public Members [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] public Object Invoke(Object obj, Object[] parameters) { // Theoretically we should set up a LookForMyCaller stack mark here and pass that along. // But to maintain backward compatibility we can't switch to calling an // internal overload that takes a stack mark. // Fortunately the stack walker skips all the reflection invocation frames including this one. // So this method will never be returned by the stack walker as the caller. // See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp. return Invoke(obj, BindingFlags.Default, null, parameters, null); } public bool IsPublic { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; } } public bool IsPrivate { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; } } public bool IsFamily { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; } } public bool IsAssembly { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly; } } public bool IsFamilyAndAssembly { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; } } public bool IsFamilyOrAssembly { get {return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; } } public bool IsStatic { get { return(Attributes & MethodAttributes.Static) != 0; } } public bool IsFinal { get { return(Attributes & MethodAttributes.Final) != 0; } } public bool IsVirtual { get { return(Attributes & MethodAttributes.Virtual) != 0; } } public bool IsHideBySig { get { return(Attributes & MethodAttributes.HideBySig) != 0; } } public bool IsAbstract { get { return(Attributes & MethodAttributes.Abstract) != 0; } } public bool IsSpecialName { get { return(Attributes & MethodAttributes.SpecialName) != 0; } } [System.Runtime.InteropServices.ComVisible(true)] public bool IsConstructor { get { // To be backward compatible we only return true for instance RTSpecialName ctors. return (this is ConstructorInfo && !IsStatic && ((Attributes & MethodAttributes.RTSpecialName) == MethodAttributes.RTSpecialName)); } } [System.Security.SecuritySafeCritical] #pragma warning disable 618 [ReflectionPermissionAttribute(SecurityAction.Demand, Flags=ReflectionPermissionFlag.MemberAccess)] #pragma warning restore 618 public virtual MethodBody GetMethodBody() { throw new InvalidOperationException(); } #endregion #region Internal Methods // helper method to construct the string representation of the parameter list // internal static string ConstructParameters(Type[] parameterTypes, CallingConventions callingConvention, bool serialization) { StringBuilder sbParamList = new StringBuilder(); string comma = ""; for (int i = 0; i < parameterTypes.Length; i++) { Type t = parameterTypes[i]; sbParamList.Append(comma); string typeName = t.FormatTypeName(serialization); // Legacy: Why use "ByRef" for by ref parameters? What language is this? // VB uses "ByRef" but it should precede (not follow) the parameter name. // Why don't we just use "&"? if (t.IsByRef && !serialization) { sbParamList.Append(typeName.TrimEnd(new char[] { '&' })); sbParamList.Append(" ByRef"); } else { sbParamList.Append(typeName); } comma = ", "; } if ((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) { sbParamList.Append(comma); sbParamList.Append("..."); } return sbParamList.ToString(); } internal string FullName { get { return String.Format("{0}.{1}", DeclaringType.FullName, FormatNameAndSig()); } } internal string FormatNameAndSig() { return FormatNameAndSig(false); } internal virtual string FormatNameAndSig(bool serialization) { // Serialization uses ToString to resolve MethodInfo overloads. StringBuilder sbName = new StringBuilder(Name); sbName.Append("("); sbName.Append(ConstructParameters(GetParameterTypes(), CallingConvention, serialization)); sbName.Append(")"); return sbName.ToString(); } internal virtual Type[] GetParameterTypes() { ParameterInfo[] paramInfo = GetParametersNoCopy(); Type[] parameterTypes = new Type[paramInfo.Length]; for (int i = 0; i < paramInfo.Length; i++) parameterTypes[i] = paramInfo[i].ParameterType; return parameterTypes; } #if !MONO [System.Security.SecuritySafeCritical] internal Object[] CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) { // copy the arguments in a different array so we detach from any user changes Object[] copyOfParameters = new Object[parameters.Length]; ParameterInfo[] p = null; for (int i = 0; i < parameters.Length; i++) { Object arg = parameters[i]; RuntimeType argRT = sig.Arguments[i]; if (arg == Type.Missing) { if (p == null) p = GetParametersNoCopy(); if (p[i].DefaultValue == System.DBNull.Value) throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters"); arg = p[i].DefaultValue; } copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr); } return copyOfParameters; } #endif #endregion void _MethodBase.GetTypeInfoCount(out uint pcTInfo) { throw new NotImplementedException(); } void _MethodBase.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) { throw new NotImplementedException(); } void _MethodBase.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) { throw new NotImplementedException(); } // If you implement this method, make sure to include _MethodBase.Invoke in VM\DangerousAPIs.h and // include _MethodBase in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. void _MethodBase.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) { throw new NotImplementedException(); } } }