diff options
Diffstat (limited to 'src/mscorlib/src/System/Reflection/MethodInfo.cs')
-rw-r--r-- | src/mscorlib/src/System/Reflection/MethodInfo.cs | 1062 |
1 files changed, 1062 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Reflection/MethodInfo.cs b/src/mscorlib/src/System/Reflection/MethodInfo.cs new file mode 100644 index 0000000000..2dd7defab5 --- /dev/null +++ b/src/mscorlib/src/System/Reflection/MethodInfo.cs @@ -0,0 +1,1062 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// + +namespace System.Reflection +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.Contracts; + using System.Globalization; + using System.Runtime; + using System.Runtime.InteropServices; + using System.Runtime.ConstrainedExecution; +#if FEATURE_REMOTING + using System.Runtime.Remoting.Metadata; +#endif //FEATURE_REMOTING + using System.Runtime.Serialization; + using System.Security; + using System.Security.Permissions; + using System.Text; + using System.Threading; + using MemberListType = System.RuntimeType.MemberListType; + using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache; + using System.Runtime.CompilerServices; + + [Serializable] + [ClassInterface(ClassInterfaceType.None)] + [ComDefaultInterface(typeof(_MethodInfo))] +#pragma warning disable 618 + [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] +#pragma warning restore 618 + [System.Runtime.InteropServices.ComVisible(true)] + public abstract class MethodInfo : MethodBase, _MethodInfo + { + #region Constructor + protected MethodInfo() { } + #endregion + +#if !FEATURE_CORECLR + public static bool operator ==(MethodInfo left, MethodInfo right) + { + if (ReferenceEquals(left, right)) + return true; + + if ((object)left == null || (object)right == null || + left is RuntimeMethodInfo || right is RuntimeMethodInfo) + { + return false; + } + return left.Equals(right); + } + + public static bool operator !=(MethodInfo left, MethodInfo right) + { + return !(left == right); + } +#endif // !FEATURE_CORECLR + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + #region MemberInfo Overrides + public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Method; } } + #endregion + + #region Public Abstract\Virtual Members + public virtual Type ReturnType { get { throw new NotImplementedException(); } } + + public virtual ParameterInfo ReturnParameter { get { throw new NotImplementedException(); } } + + public abstract ICustomAttributeProvider ReturnTypeCustomAttributes { get; } + + public abstract MethodInfo GetBaseDefinition(); + + [System.Runtime.InteropServices.ComVisible(true)] + public override Type[] GetGenericArguments() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } + + [System.Runtime.InteropServices.ComVisible(true)] + public virtual MethodInfo GetGenericMethodDefinition() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } + + public virtual MethodInfo MakeGenericMethod(params Type[] typeArguments) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } + + public virtual Delegate CreateDelegate(Type delegateType) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } + public virtual Delegate CreateDelegate(Type delegateType, Object target) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } + #endregion + +#if !FEATURE_CORECLR + Type _MethodInfo.GetType() + { + return base.GetType(); + } + + void _MethodInfo.GetTypeInfoCount(out uint pcTInfo) + { + throw new NotImplementedException(); + } + + void _MethodInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) + { + throw new NotImplementedException(); + } + + void _MethodInfo.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 _MethodInfo.Invoke in VM\DangerousAPIs.h and + // include _MethodInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. + void _MethodInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) + { + throw new NotImplementedException(); + } +#endif + } + + [Serializable] + internal sealed class RuntimeMethodInfo : MethodInfo, ISerializable, IRuntimeMethodInfo + { + #region Private Data Members + private IntPtr m_handle; + private RuntimeTypeCache m_reflectedTypeCache; + private string m_name; + private string m_toString; + private ParameterInfo[] m_parameters; + private ParameterInfo m_returnParameter; + private BindingFlags m_bindingFlags; + private MethodAttributes m_methodAttributes; + private Signature m_signature; + private RuntimeType m_declaringType; + private object m_keepalive; + private INVOCATION_FLAGS m_invocationFlags; + +#if FEATURE_APPX + private bool IsNonW8PFrameworkAPI() + { + if (m_declaringType.IsArray && IsPublic && !IsStatic) + return false; + + RuntimeAssembly rtAssembly = GetRuntimeAssembly(); + if (rtAssembly.IsFrameworkAssembly()) + { + int ctorToken = rtAssembly.InvocableAttributeCtorToken; + if (System.Reflection.MetadataToken.IsNullToken(ctorToken) || + !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken)) + return true; + } + + if (GetRuntimeType().IsNonW8PFrameworkAPI()) + return true; + + if (IsGenericMethod && !IsGenericMethodDefinition) + { + foreach (Type t in GetGenericArguments()) + { + if (((RuntimeType)t).IsNonW8PFrameworkAPI()) + return true; + } + } + + return false; + } + + internal override bool IsDynamicallyInvokable + { + get + { + return !AppDomain.ProfileAPICheck || !IsNonW8PFrameworkAPI(); + } + } +#endif + + internal INVOCATION_FLAGS InvocationFlags + { + [System.Security.SecuritySafeCritical] + get + { + if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) + { + INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN; + + Type declaringType = DeclaringType; + + // + // first take care of all the NO_INVOKE cases. + if (ContainsGenericParameters || + ReturnType.IsByRef || + (declaringType != null && declaringType.ContainsGenericParameters) || + ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) || + ((Attributes & MethodAttributes.RequireSecObject) == MethodAttributes.RequireSecObject)) + { + // We don't need other flags if this method cannot be invoked + invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + } + else + { + // this should be an invocable method, determine the other flags that participate in invocation + invocationFlags = RuntimeMethodHandle.GetSecurityFlags(this); + + if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) == 0) + { + if ( (Attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public || + (declaringType != null && declaringType.NeedsReflectionSecurityCheck) ) + { + // If method is non-public, or declaring type is not visible + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY; + } + else if (IsGenericMethod) + { + Type[] genericArguments = GetGenericArguments(); + + for (int i = 0; i < genericArguments.Length; i++) + { + if (genericArguments[i].NeedsReflectionSecurityCheck) + { + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY; + break; + } + } + } + } + } + +#if FEATURE_APPX + if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI()) + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API; +#endif // FEATURE_APPX + + m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; + } + + return m_invocationFlags; + } + } + #endregion + + #region Constructor + [System.Security.SecurityCritical] // auto-generated + internal RuntimeMethodInfo( + RuntimeMethodHandleInternal handle, RuntimeType declaringType, + RuntimeTypeCache reflectedTypeCache, MethodAttributes methodAttributes, BindingFlags bindingFlags, object keepalive) + { + Contract.Ensures(!m_handle.IsNull()); + + Contract.Assert(!handle.IsNullHandle()); + Contract.Assert(methodAttributes == RuntimeMethodHandle.GetAttributes(handle)); + + m_bindingFlags = bindingFlags; + m_declaringType = declaringType; + m_keepalive = keepalive; + m_handle = handle.Value; + m_reflectedTypeCache = reflectedTypeCache; + m_methodAttributes = methodAttributes; + } + #endregion + +#if FEATURE_REMOTING + #region Legacy Remoting Cache + // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h. + // This member is currently being used by Remoting for caching remoting data. If you + // need to cache data here, talk to the Remoting team to work out a mechanism, so that + // both caching systems can happily work together. + private RemotingMethodCachedData m_cachedData; + + internal RemotingMethodCachedData RemotingCache + { + get + { + // This grabs an internal copy of m_cachedData and uses + // that instead of looking at m_cachedData directly because + // the cache may get cleared asynchronously. This prevents + // us from having to take a lock. + RemotingMethodCachedData cache = m_cachedData; + if (cache == null) + { + cache = new RemotingMethodCachedData(this); + RemotingMethodCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null); + if (ret != null) + cache = ret; + } + return cache; + } + } + #endregion +#endif //FEATURE_REMOTING + + #region Private Methods + RuntimeMethodHandleInternal IRuntimeMethodInfo.Value + { + [System.Security.SecuritySafeCritical] + get + { + return new RuntimeMethodHandleInternal(m_handle); + } + } + + private RuntimeType ReflectedTypeInternal + { + get + { + return m_reflectedTypeCache.GetRuntimeType(); + } + } + + [System.Security.SecurityCritical] // auto-generated + private ParameterInfo[] FetchNonReturnParameters() + { + if (m_parameters == null) + m_parameters = RuntimeParameterInfo.GetParameters(this, this, Signature); + + return m_parameters; + } + + [System.Security.SecurityCritical] // auto-generated + private ParameterInfo FetchReturnParameter() + { + if (m_returnParameter == null) + m_returnParameter = RuntimeParameterInfo.GetReturnParameter(this, this, Signature); + + return m_returnParameter; + } + #endregion + + #region Internal Members + internal override string FormatNameAndSig(bool serialization) + { + // Serialization uses ToString to resolve MethodInfo overloads. + StringBuilder sbName = new StringBuilder(Name); + + // serialization == true: use unambiguous (except for assembly name) type names to distinguish between overloads. + // serialization == false: use basic format to maintain backward compatibility of MethodInfo.ToString(). + TypeNameFormatFlags format = serialization ? TypeNameFormatFlags.FormatSerialization : TypeNameFormatFlags.FormatBasic; + + if (IsGenericMethod) + sbName.Append(RuntimeMethodHandle.ConstructInstantiation(this, format)); + + sbName.Append("("); + sbName.Append(ConstructParameters(GetParameterTypes(), CallingConvention, serialization)); + sbName.Append(")"); + + return sbName.ToString(); + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + internal override bool CacheEquals(object o) + { + RuntimeMethodInfo m = o as RuntimeMethodInfo; + + if ((object)m == null) + return false; + + return m.m_handle == m_handle; + } + + internal Signature Signature + { + get + { + if (m_signature == null) + m_signature = new Signature(this, m_declaringType); + + return m_signature; + } + } + + internal BindingFlags BindingFlags { get { return m_bindingFlags; } } + + // Differs from MethodHandle in that it will return a valid handle even for reflection only loaded types + internal RuntimeMethodHandle GetMethodHandle() + { + return new RuntimeMethodHandle(this); + } + + [System.Security.SecuritySafeCritical] // auto-generated + internal RuntimeMethodInfo GetParentDefinition() + { + if (!IsVirtual || m_declaringType.IsInterface) + return null; + + RuntimeType parent = (RuntimeType)m_declaringType.BaseType; + + if (parent == null) + return null; + + int slot = RuntimeMethodHandle.GetSlot(this); + + if (RuntimeTypeHandle.GetNumVirtuals(parent) <= slot) + return null; + + return (RuntimeMethodInfo)RuntimeType.GetMethodBase(parent, RuntimeTypeHandle.GetMethodAt(parent, slot)); + } + + // Unlike DeclaringType, this will return a valid type even for global methods + internal RuntimeType GetDeclaringTypeInternal() + { + return m_declaringType; + } + + #endregion + + #region Object Overrides + public override String ToString() + { + if (m_toString == null) + m_toString = ReturnType.FormatTypeName() + " " + FormatNameAndSig(); + + return m_toString; + } + + public override int GetHashCode() + { + // See RuntimeMethodInfo.Equals() below. + if (IsGenericMethod) + return ValueType.GetHashCodeOfPtr(m_handle); + else + return base.GetHashCode(); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public override bool Equals(object obj) + { + if (!IsGenericMethod) + return obj == (object)this; + + // We cannot do simple object identity comparisons for generic methods. + // Equals will be called in CerHashTable when RuntimeType+RuntimeTypeCache.GetGenericMethodInfo() + // retrive items from and insert items into s_methodInstantiations which is a CerHashtable. + + RuntimeMethodInfo mi = obj as RuntimeMethodInfo; + + if (mi == null || !mi.IsGenericMethod) + return false; + + // now we know that both operands are generic methods + + IRuntimeMethodInfo handle1 = RuntimeMethodHandle.StripMethodInstantiation(this); + IRuntimeMethodInfo handle2 = RuntimeMethodHandle.StripMethodInstantiation(mi); + if (handle1.Value.Value != handle2.Value.Value) + return false; + + Type[] lhs = GetGenericArguments(); + Type[] rhs = mi.GetGenericArguments(); + + if (lhs.Length != rhs.Length) + return false; + + for (int i = 0; i < lhs.Length; i++) + { + if (lhs[i] != rhs[i]) + return false; + } + + if (DeclaringType != mi.DeclaringType) + return false; + + if (ReflectedType != mi.ReflectedType) + return false; + + return true; + } + #endregion + + #region ICustomAttributeProvider + [System.Security.SecuritySafeCritical] // auto-generated + public override Object[] GetCustomAttributes(bool inherit) + { + return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType as RuntimeType, inherit); + } + + [System.Security.SecuritySafeCritical] // auto-generated + public override Object[] GetCustomAttributes(Type attributeType, bool inherit) + { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + Contract.EndContractBlock(); + + RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; + + if (attributeRuntimeType == null) + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + + return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + Contract.EndContractBlock(); + + RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; + + if (attributeRuntimeType == null) + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + + return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit); + } + + public override IList<CustomAttributeData> GetCustomAttributesData() + { + return CustomAttributeData.GetCustomAttributesInternal(this); + } + #endregion + + #region MemberInfo Overrides + public override String Name + { + [System.Security.SecuritySafeCritical] // auto-generated + get + { + if (m_name == null) + m_name = RuntimeMethodHandle.GetName(this); + + return m_name; + } + } + + public override Type DeclaringType + { + get + { + if (m_reflectedTypeCache.IsGlobal) + return null; + + return m_declaringType; + } + } + + public override Type ReflectedType + { + get + { + if (m_reflectedTypeCache.IsGlobal) + return null; + + return m_reflectedTypeCache.GetRuntimeType(); + } + } + + public override MemberTypes MemberType { get { return MemberTypes.Method; } } + public override int MetadataToken + { + [System.Security.SecuritySafeCritical] // auto-generated + get { return RuntimeMethodHandle.GetMethodDef(this); } + } + public override Module Module { get { return GetRuntimeModule(); } } + internal RuntimeType GetRuntimeType() { return m_declaringType; } + internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); } + internal RuntimeAssembly GetRuntimeAssembly() { return GetRuntimeModule().GetRuntimeAssembly(); } + + public override bool IsSecurityCritical + { + get { return RuntimeMethodHandle.IsSecurityCritical(this); } + } + public override bool IsSecuritySafeCritical + { + get { return RuntimeMethodHandle.IsSecuritySafeCritical(this); } + } + public override bool IsSecurityTransparent + { + get { return RuntimeMethodHandle.IsSecurityTransparent(this); } + } + #endregion + + #region MethodBase Overrides + [System.Security.SecuritySafeCritical] // auto-generated + internal override ParameterInfo[] GetParametersNoCopy() + { + FetchNonReturnParameters(); + + return m_parameters; + } + + [System.Security.SecuritySafeCritical] // auto-generated + [System.Diagnostics.Contracts.Pure] + public override ParameterInfo[] GetParameters() + { + FetchNonReturnParameters(); + + if (m_parameters.Length == 0) + return m_parameters; + + ParameterInfo[] ret = new ParameterInfo[m_parameters.Length]; + + Array.Copy(m_parameters, ret, m_parameters.Length); + + return ret; + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + return RuntimeMethodHandle.GetImplAttributes(this); + } + + internal bool IsOverloaded + { + get + { + return m_reflectedTypeCache.GetMethodList(MemberListType.CaseSensitive, Name).Length > 1; + } + } + + public override RuntimeMethodHandle MethodHandle + { + get + { + Type declaringType = DeclaringType; + if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly")); + return new RuntimeMethodHandle(this); + } + } + + public override MethodAttributes Attributes { get { return m_methodAttributes; } } + + public override CallingConventions CallingConvention + { + get + { + return Signature.CallingConvention; + } + } + + [System.Security.SecuritySafeCritical] // overrides SafeCritical member +#if !FEATURE_CORECLR +#pragma warning disable 618 + [ReflectionPermissionAttribute(SecurityAction.Demand, Flags = ReflectionPermissionFlag.MemberAccess)] +#pragma warning restore 618 +#endif + public override MethodBody GetMethodBody() + { + MethodBody mb = RuntimeMethodHandle.GetMethodBody(this, ReflectedTypeInternal); + if (mb != null) + mb.m_methodBase = this; + return mb; + } + #endregion + + #region Invocation Logic(On MemberBase) + private void CheckConsistency(Object target) + { + // only test instance methods + if ((m_methodAttributes & MethodAttributes.Static) != MethodAttributes.Static) + { + if (!m_declaringType.IsInstanceOfType(target)) + { + if (target == null) + throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatMethReqTarg")); + else + throw new TargetException(Environment.GetResourceString("RFLCT.Targ_ITargMismatch")); + } + } + } + + [System.Security.SecuritySafeCritical] + private void ThrowNoInvokeException() + { + // method is ReflectionOnly + Type declaringType = DeclaringType; + if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType) + { + throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyInvoke")); + } + // method is on a class that contains stack pointers + else if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS) != 0) + { + throw new NotSupportedException(); + } + // method is vararg + else if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) + { + throw new NotSupportedException(); + } + // method is generic or on a generic class + else if (DeclaringType.ContainsGenericParameters || ContainsGenericParameters) + { + throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenParam")); + } + // method is abstract class + else if (IsAbstract) + { + throw new MemberAccessException(); + } + // ByRef return are not allowed in reflection + else if (ReturnType.IsByRef) + { + throw new NotSupportedException(Environment.GetResourceString("NotSupported_ByRefReturn")); + } + + throw new TargetException(); + } + + [System.Security.SecuritySafeCritical] + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) + { + object[] arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture); + + #region Security Check + INVOCATION_FLAGS invocationFlags = InvocationFlags; + +#if FEATURE_APPX + if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark); + if (caller != null && !caller.IsSafeForReflection()) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName)); + } +#endif + + if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0) + { +#if !FEATURE_CORECLR + if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0) + CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess); + + if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0) +#endif // !FEATURE_CORECLR + RuntimeMethodHandle.PerformSecurityCheck(obj, this, m_declaringType, (uint)m_invocationFlags); + } + #endregion + + return UnsafeInvokeInternal(obj, parameters, arguments); + } + + [System.Security.SecurityCritical] + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + internal object UnsafeInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) + { + object[] arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture); + + return UnsafeInvokeInternal(obj, parameters, arguments); + } + + [System.Security.SecurityCritical] + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + private object UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) + { + if (arguments == null || arguments.Length == 0) + return RuntimeMethodHandle.InvokeMethod(obj, null, Signature, false); + else + { + Object retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false); + + // copy out. This should be made only if ByRef are present. + for (int index = 0; index < arguments.Length; index++) + parameters[index] = arguments[index]; + + return retValue; + } + } + + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + private object[] InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) + { + Signature sig = Signature; + + // get the signature + int formalCount = sig.Arguments.Length; + int actualCount = (parameters != null) ? parameters.Length : 0; + + INVOCATION_FLAGS invocationFlags = InvocationFlags; + + // INVOCATION_FLAGS_CONTAINS_STACK_POINTERS means that the struct (either the declaring type or the return type) + // contains pointers that point to the stack. This is either a ByRef or a TypedReference. These structs cannot + // be boxed and thus cannot be invoked through reflection which only deals with boxed value type objects. + if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS)) != 0) + ThrowNoInvokeException(); + + // check basic method consistency. This call will throw if there are problems in the target/method relationship + CheckConsistency(obj); + + if (formalCount != actualCount) + throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt")); + + if (actualCount != 0) + return CheckArguments(parameters, binder, invokeAttr, culture, sig); + else + return null; + } + + #endregion + + #region MethodInfo Overrides + public override Type ReturnType + { + get { return Signature.ReturnType; } + } + + public override ICustomAttributeProvider ReturnTypeCustomAttributes + { + get { return ReturnParameter; } + } + + public override ParameterInfo ReturnParameter + { + [System.Security.SecuritySafeCritical] // auto-generated + get + { + Contract.Ensures(m_returnParameter != null); + + FetchReturnParameter(); + return m_returnParameter as ParameterInfo; + } + } + + [System.Security.SecuritySafeCritical] // auto-generated + public override MethodInfo GetBaseDefinition() + { + if (!IsVirtual || IsStatic || m_declaringType == null || m_declaringType.IsInterface) + return this; + + int slot = RuntimeMethodHandle.GetSlot(this); + RuntimeType declaringType = (RuntimeType)DeclaringType; + RuntimeType baseDeclaringType = declaringType; + RuntimeMethodHandleInternal baseMethodHandle = new RuntimeMethodHandleInternal(); + + do { + int cVtblSlots = RuntimeTypeHandle.GetNumVirtuals(declaringType); + + if (cVtblSlots <= slot) + break; + + baseMethodHandle = RuntimeTypeHandle.GetMethodAt(declaringType, slot); + baseDeclaringType = declaringType; + + declaringType = (RuntimeType)declaringType.BaseType; + } while (declaringType != null); + + return(MethodInfo)RuntimeType.GetMethodBase(baseDeclaringType, baseMethodHandle); + } + + [System.Security.SecuritySafeCritical] + public override Delegate CreateDelegate(Type delegateType) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + + // This API existed in v1/v1.1 and only expected to create closed + // instance delegates. Constrain the call to BindToMethodInfo to + // open delegates only for backwards compatibility. But we'll allow + // relaxed signature checking and open static delegates because + // there's no ambiguity there (the caller would have to explicitly + // pass us a static method or a method with a non-exact signature + // and the only change in behavior from v1.1 there is that we won't + // fail the call). + return CreateDelegateInternal( + delegateType, + null, + DelegateBindingFlags.OpenDelegateOnly | DelegateBindingFlags.RelaxedSignature, + ref stackMark); + } + + [System.Security.SecuritySafeCritical] + public override Delegate CreateDelegate(Type delegateType, Object target) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + + // This API is new in Whidbey and allows the full range of delegate + // flexability (open or closed delegates binding to static or + // instance methods with relaxed signature checking). The delegate + // can also be closed over null. There's no ambiguity with all these + // options since the caller is providing us a specific MethodInfo. + return CreateDelegateInternal( + delegateType, + target, + DelegateBindingFlags.RelaxedSignature, + ref stackMark); + } + + [System.Security.SecurityCritical] + private Delegate CreateDelegateInternal(Type delegateType, Object firstArgument, DelegateBindingFlags bindingFlags, ref StackCrawlMark stackMark) + { + // Validate the parameters. + if (delegateType == null) + throw new ArgumentNullException("delegateType"); + Contract.EndContractBlock(); + + RuntimeType rtType = delegateType as RuntimeType; + if (rtType == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "delegateType"); + + if (!rtType.IsDelegate()) + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "delegateType"); + + Delegate d = Delegate.CreateDelegateInternal(rtType, this, firstArgument, bindingFlags, ref stackMark); + if (d == null) + { + throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth")); + } + + return d; + } + + #endregion + + #region Generics + [System.Security.SecuritySafeCritical] // auto-generated + public override MethodInfo MakeGenericMethod(params Type[] methodInstantiation) + { + if (methodInstantiation == null) + throw new ArgumentNullException("methodInstantiation"); + Contract.EndContractBlock(); + + RuntimeType[] methodInstantionRuntimeType = new RuntimeType[methodInstantiation.Length]; + + if (!IsGenericMethodDefinition) + throw new InvalidOperationException( + Environment.GetResourceString("Arg_NotGenericMethodDefinition", this)); + + for (int i = 0; i < methodInstantiation.Length; i++) + { + Type methodInstantiationElem = methodInstantiation[i]; + + if (methodInstantiationElem == null) + throw new ArgumentNullException(); + + RuntimeType rtMethodInstantiationElem = methodInstantiationElem as RuntimeType; + + if (rtMethodInstantiationElem == null) + { + Type[] methodInstantiationCopy = new Type[methodInstantiation.Length]; + for (int iCopy = 0; iCopy < methodInstantiation.Length; iCopy++) + methodInstantiationCopy[iCopy] = methodInstantiation[iCopy]; + methodInstantiation = methodInstantiationCopy; + return System.Reflection.Emit.MethodBuilderInstantiation.MakeGenericMethod(this, methodInstantiation); + } + + methodInstantionRuntimeType[i] = rtMethodInstantiationElem; + } + + RuntimeType[] genericParameters = GetGenericArgumentsInternal(); + + RuntimeType.SanityCheckGenericArguments(methodInstantionRuntimeType, genericParameters); + + MethodInfo ret = null; + + try + { + ret = RuntimeType.GetMethodBase(ReflectedTypeInternal, + RuntimeMethodHandle.GetStubIfNeeded(new RuntimeMethodHandleInternal(this.m_handle), m_declaringType, methodInstantionRuntimeType)) as MethodInfo; + } + catch (VerificationException e) + { + RuntimeType.ValidateGenericArguments(this, methodInstantionRuntimeType, e); + throw; + } + + return ret; + } + + internal RuntimeType[] GetGenericArgumentsInternal() + { + return RuntimeMethodHandle.GetMethodInstantiationInternal(this); + } + + public override Type[] GetGenericArguments() + { + Type[] types = RuntimeMethodHandle.GetMethodInstantiationPublic(this); + + if (types == null) + { + types = EmptyArray<Type>.Value; + } + return types; + } + + public override MethodInfo GetGenericMethodDefinition() + { + if (!IsGenericMethod) + throw new InvalidOperationException(); + Contract.EndContractBlock(); + + return RuntimeType.GetMethodBase(m_declaringType, RuntimeMethodHandle.StripMethodInstantiation(this)) as MethodInfo; + } + + public override bool IsGenericMethod + { + get { return RuntimeMethodHandle.HasMethodInstantiation(this); } + } + + public override bool IsGenericMethodDefinition + { + get { return RuntimeMethodHandle.IsGenericMethodDefinition(this); } + } + + public override bool ContainsGenericParameters + { + get + { + if (DeclaringType != null && DeclaringType.ContainsGenericParameters) + return true; + + if (!IsGenericMethod) + return false; + + Type[] pis = GetGenericArguments(); + for (int i = 0; i < pis.Length; i++) + { + if (pis[i].ContainsGenericParameters) + return true; + } + + return false; + } + } + #endregion + + #region ISerializable Implementation + [System.Security.SecurityCritical] // auto-generated + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + Contract.EndContractBlock(); + + if (m_reflectedTypeCache.IsGlobal) + throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalMethodSerialization")); + + MemberInfoSerializationHolder.GetSerializationInfo( + info, + Name, + ReflectedTypeInternal, + ToString(), + SerializationToString(), + MemberTypes.Method, + IsGenericMethod & !IsGenericMethodDefinition ? GetGenericArguments() : null); + } + + internal string SerializationToString() + { + return ReturnType.FormatTypeName(true) + " " + FormatNameAndSig(true); + } + #endregion + + #region Legacy Internal + internal static MethodBase InternalGetCurrentMethod(ref StackCrawlMark stackMark) + { + IRuntimeMethodInfo method = RuntimeMethodHandle.GetCurrentMethod(ref stackMark); + + if (method == null) + return null; + + return RuntimeType.GetMethodBase(method); + } + #endregion + } +} |