1116 lines
42 KiB
C#
1116 lines
42 KiB
C#
// ==++==
|
|
//
|
|
// Copyright(c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ==--==
|
|
// <OWNER>[....]</OWNER>
|
|
//
|
|
|
|
namespace System.Reflection
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.Contracts;
|
|
using System.Diagnostics.Tracing;
|
|
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);
|
|
}
|
|
|
|
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
|
public static bool operator !=(MethodInfo left, MethodInfo 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 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
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
[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)]
|
|
#if !FEATURE_CORECLR
|
|
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
|
#endif
|
|
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);
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.MethodName(GetDeclaringTypeInternal().GetFullNameForEtw(), GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
return m_name;
|
|
}
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical]
|
|
internal override String GetFullNameForEtw()
|
|
{
|
|
if (m_name == null)
|
|
return 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
|
|
#if !FEATURE_CORECLR
|
|
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
|
#endif
|
|
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
|
|
#pragma warning disable 618
|
|
[ReflectionPermissionAttribute(SecurityAction.Demand, Flags = ReflectionPermissionFlag.MemberAccess)]
|
|
#pragma warning restore 618
|
|
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
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.MethodInfoInvoke(GetRuntimeType() != null ? GetRuntimeType().GetFullNameForEtw() : "", GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.MethodInfoInvoke(GetRuntimeType() != null ? GetRuntimeType().GetFullNameForEtw() : "", GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
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");
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.BeginMethodInfoCreateDelegate(GetRuntimeType() != null ? GetRuntimeType().GetFullNameForEtw() : "", GetFullNameForEtw(),rtType.GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
Delegate d = Delegate.CreateDelegateInternal(rtType, this, firstArgument, bindingFlags, ref stackMark);
|
|
if (d == null)
|
|
{
|
|
throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
|
|
}
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.EndMethodInfoCreateDelegate(GetRuntimeType() != null ? GetRuntimeType().GetFullNameForEtw() : "", GetFullNameForEtw(),rtType.GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
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
|
|
}
|
|
}
|