1038 lines
40 KiB
C#
1038 lines
40 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.CompilerServices;
|
|
using System.Runtime.ConstrainedExecution;
|
|
using System.Runtime.InteropServices;
|
|
#if FEATURE_REMOTING
|
|
using System.Runtime.Remoting.Metadata;
|
|
#endif //FEATURE_REMOTING
|
|
using System.Runtime.Serialization;
|
|
using System.Security.Permissions;
|
|
using System.Threading;
|
|
using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
|
|
|
|
[Serializable]
|
|
[ClassInterface(ClassInterfaceType.None)]
|
|
[ComDefaultInterface(typeof(_FieldInfo))]
|
|
#pragma warning disable 618
|
|
[PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
|
|
#pragma warning restore 618
|
|
[System.Runtime.InteropServices.ComVisible(true)]
|
|
public abstract class FieldInfo : MemberInfo, _FieldInfo
|
|
{
|
|
#region Static Members
|
|
public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle handle)
|
|
{
|
|
if (handle.IsNullHandle())
|
|
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.BeginGetFieldFromHandle();
|
|
}
|
|
#endif
|
|
|
|
FieldInfo f = RuntimeType.GetFieldInfo(handle.GetRuntimeFieldInfo());
|
|
|
|
Type declaringType = f.DeclaringType;
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage) && declaringType != null && f != null)
|
|
{
|
|
FrameworkEventSource.Log.EndGetFieldFromHandle(declaringType.GetFullNameForEtw(), f.GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
if (declaringType != null && declaringType.IsGenericType)
|
|
throw new ArgumentException(String.Format(
|
|
CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_FieldDeclaringTypeGeneric"),
|
|
f.Name, declaringType.GetGenericTypeDefinition()));
|
|
|
|
return f;
|
|
}
|
|
|
|
[System.Runtime.InteropServices.ComVisible(false)]
|
|
public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle handle, RuntimeTypeHandle declaringType)
|
|
{
|
|
if (handle.IsNullHandle())
|
|
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.BeginGetFieldFromHandle();
|
|
}
|
|
#endif
|
|
|
|
FieldInfo f = RuntimeType.GetFieldInfo(declaringType.GetRuntimeType(), handle.GetRuntimeFieldInfo());
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage) && declaringType != null && f != null)
|
|
{
|
|
FrameworkEventSource.Log.EndGetFieldFromHandle(declaringType.GetRuntimeType().GetFullNameForEtw(), f.GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
return f;
|
|
}
|
|
#endregion
|
|
|
|
#region Constructor
|
|
protected FieldInfo() { }
|
|
#endregion
|
|
|
|
#if !FEATURE_CORECLR
|
|
public static bool operator ==(FieldInfo left, FieldInfo right)
|
|
{
|
|
if (ReferenceEquals(left, right))
|
|
return true;
|
|
|
|
if ((object)left == null || (object)right == null ||
|
|
left is RuntimeFieldInfo || right is RuntimeFieldInfo)
|
|
{
|
|
return false;
|
|
}
|
|
return left.Equals(right);
|
|
}
|
|
|
|
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
|
public static bool operator !=(FieldInfo left, FieldInfo 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.Field; } }
|
|
#endregion
|
|
|
|
#region Public Abstract\Virtual Members
|
|
|
|
public virtual Type[] GetRequiredCustomModifiers()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public virtual Type[] GetOptionalCustomModifiers()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public virtual void SetValueDirect(TypedReference obj, Object value)
|
|
{
|
|
throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS"));
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public virtual Object GetValueDirect(TypedReference obj)
|
|
{
|
|
throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS"));
|
|
}
|
|
|
|
public abstract RuntimeFieldHandle FieldHandle { get; }
|
|
|
|
public abstract Type FieldType { get; }
|
|
|
|
public abstract Object GetValue(Object obj);
|
|
|
|
public virtual Object GetRawConstantValue() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS")); }
|
|
|
|
public abstract void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture);
|
|
|
|
public abstract FieldAttributes Attributes { get; }
|
|
#endregion
|
|
|
|
#region Public Members
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public void SetValue(Object obj, Object value)
|
|
{
|
|
// 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.
|
|
SetValue(obj, value, BindingFlags.Default, Type.DefaultBinder, null);
|
|
}
|
|
|
|
public bool IsPublic { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; } }
|
|
|
|
public bool IsPrivate { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private; } }
|
|
|
|
public bool IsFamily { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; } }
|
|
|
|
public bool IsAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly; } }
|
|
|
|
public bool IsFamilyAndAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem; } }
|
|
|
|
public bool IsFamilyOrAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem; } }
|
|
|
|
public bool IsStatic { get { return(Attributes & FieldAttributes.Static) != 0; } }
|
|
|
|
public bool IsInitOnly { get { return(Attributes & FieldAttributes.InitOnly) != 0; } }
|
|
|
|
public bool IsLiteral { get { return(Attributes & FieldAttributes.Literal) != 0; } }
|
|
|
|
public bool IsNotSerialized { get { return(Attributes & FieldAttributes.NotSerialized) != 0; } }
|
|
|
|
public bool IsSpecialName { get { return(Attributes & FieldAttributes.SpecialName) != 0; } }
|
|
|
|
public bool IsPinvokeImpl { get { return(Attributes & FieldAttributes.PinvokeImpl) != 0; } }
|
|
|
|
public virtual bool IsSecurityCritical
|
|
{
|
|
get { return FieldHandle.IsSecurityCritical(); }
|
|
}
|
|
|
|
public virtual bool IsSecuritySafeCritical
|
|
{
|
|
get { return FieldHandle.IsSecuritySafeCritical(); }
|
|
}
|
|
|
|
public virtual bool IsSecurityTransparent
|
|
{
|
|
get { return FieldHandle.IsSecurityTransparent(); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
Type _FieldInfo.GetType()
|
|
{
|
|
return base.GetType();
|
|
}
|
|
|
|
void _FieldInfo.GetTypeInfoCount(out uint pcTInfo)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
void _FieldInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
void _FieldInfo.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 _FieldInfo.Invoke in VM\DangerousAPIs.h and
|
|
// include _FieldInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
|
|
void _FieldInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
internal abstract class RuntimeFieldInfo : FieldInfo, ISerializable
|
|
{
|
|
#region Private Data Members
|
|
private BindingFlags m_bindingFlags;
|
|
protected RuntimeTypeCache m_reflectedTypeCache;
|
|
protected RuntimeType m_declaringType;
|
|
#endregion
|
|
|
|
#region Constructor
|
|
protected RuntimeFieldInfo()
|
|
{
|
|
// Used for dummy head node during population
|
|
}
|
|
protected RuntimeFieldInfo(RuntimeTypeCache reflectedTypeCache, RuntimeType declaringType, BindingFlags bindingFlags)
|
|
{
|
|
m_bindingFlags = bindingFlags;
|
|
m_declaringType = declaringType;
|
|
m_reflectedTypeCache = reflectedTypeCache;
|
|
}
|
|
#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 RemotingFieldCachedData m_cachedData;
|
|
|
|
internal RemotingFieldCachedData 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.
|
|
RemotingFieldCachedData cache = m_cachedData;
|
|
if (cache == null)
|
|
{
|
|
cache = new RemotingFieldCachedData(this);
|
|
RemotingFieldCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
|
|
if (ret != null)
|
|
cache = ret;
|
|
}
|
|
return cache;
|
|
}
|
|
}
|
|
#endregion
|
|
#endif //FEATURE_REMOTING
|
|
|
|
#region NonPublic Members
|
|
internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
|
|
private RuntimeType ReflectedTypeInternal
|
|
{
|
|
get
|
|
{
|
|
return m_reflectedTypeCache.GetRuntimeType();
|
|
}
|
|
}
|
|
|
|
internal RuntimeType GetDeclaringTypeInternal()
|
|
{
|
|
return m_declaringType;
|
|
}
|
|
|
|
internal RuntimeType GetRuntimeType() { return m_declaringType; }
|
|
internal abstract RuntimeModule GetRuntimeModule();
|
|
#endregion
|
|
|
|
#region MemberInfo Overrides
|
|
public override MemberTypes MemberType { get { return MemberTypes.Field; } }
|
|
public override Type ReflectedType
|
|
{
|
|
get
|
|
{
|
|
return m_reflectedTypeCache.IsGlobal ? null : ReflectedTypeInternal;
|
|
}
|
|
}
|
|
|
|
public override Type DeclaringType
|
|
{
|
|
get
|
|
{
|
|
return m_reflectedTypeCache.IsGlobal ? null : m_declaringType;
|
|
}
|
|
}
|
|
|
|
public override Module Module { get { return GetRuntimeModule(); } }
|
|
#endregion
|
|
|
|
#region Object Overrides
|
|
public unsafe override String ToString()
|
|
{
|
|
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
|
|
return FieldType.ToString() + " " + Name;
|
|
else
|
|
return FieldType.FormatTypeName() + " " + Name;
|
|
}
|
|
#endregion
|
|
|
|
#region ICustomAttributeProvider
|
|
public override Object[] GetCustomAttributes(bool inherit)
|
|
{
|
|
return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
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);
|
|
}
|
|
|
|
public override IList<CustomAttributeData> GetCustomAttributesData()
|
|
{
|
|
return CustomAttributeData.GetCustomAttributesInternal(this);
|
|
}
|
|
#endregion
|
|
|
|
#region FieldInfo Overrides
|
|
// All implemented on derived classes
|
|
#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();
|
|
MemberInfoSerializationHolder.GetSerializationInfo(
|
|
info,
|
|
Name,
|
|
ReflectedTypeInternal,
|
|
ToString(),
|
|
MemberTypes.Field);
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
[Serializable]
|
|
internal unsafe sealed class RtFieldInfo : RuntimeFieldInfo, IRuntimeFieldInfo
|
|
{
|
|
#region FCalls
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
[System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.None)]
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
static private extern void PerformVisibilityCheckOnField(IntPtr field, Object target, RuntimeType declaringType, FieldAttributes attr, uint invocationFlags);
|
|
#endregion
|
|
|
|
#region Private Data Members
|
|
// agressive caching
|
|
#if !FEATURE_CORECLR
|
|
[System.Runtime.ForceTokenStabilization]
|
|
#endif //!FEATURE_CORECLR
|
|
private IntPtr m_fieldHandle;
|
|
private FieldAttributes m_fieldAttributes;
|
|
// lazy caching
|
|
private string m_name;
|
|
private RuntimeType m_fieldType;
|
|
private INVOCATION_FLAGS m_invocationFlags;
|
|
|
|
#if FEATURE_APPX
|
|
private bool IsNonW8PFrameworkAPI()
|
|
{
|
|
if (GetRuntimeType().IsNonW8PFrameworkAPI())
|
|
return true;
|
|
|
|
// Allow "value__"
|
|
if (m_declaringType.IsEnum)
|
|
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;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
internal INVOCATION_FLAGS InvocationFlags
|
|
{
|
|
get
|
|
{
|
|
if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
|
|
{
|
|
Type declaringType = DeclaringType;
|
|
bool fIsReflectionOnlyType = (declaringType is ReflectionOnlyType);
|
|
|
|
INVOCATION_FLAGS invocationFlags = 0;
|
|
|
|
// first take care of all the NO_INVOKE cases
|
|
if (
|
|
(declaringType != null && declaringType.ContainsGenericParameters) ||
|
|
(declaringType == null && Module.Assembly.ReflectionOnly) ||
|
|
(fIsReflectionOnlyType)
|
|
)
|
|
{
|
|
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE;
|
|
}
|
|
|
|
// If the invocationFlags are still 0, then
|
|
// this should be an usable field, determine the other flags
|
|
if (invocationFlags == 0)
|
|
{
|
|
if ((m_fieldAttributes & FieldAttributes.InitOnly) != (FieldAttributes)0)
|
|
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD;
|
|
|
|
if ((m_fieldAttributes & FieldAttributes.HasFieldRVA) != (FieldAttributes)0)
|
|
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD;
|
|
|
|
// A public field is inaccesible to Transparent code if the field is Critical.
|
|
bool needsTransparencySecurityCheck = IsSecurityCritical && !IsSecuritySafeCritical;
|
|
bool needsVisibilitySecurityCheck = ((m_fieldAttributes & FieldAttributes.FieldAccessMask) != FieldAttributes.Public) ||
|
|
(declaringType != null && declaringType.NeedsReflectionSecurityCheck);
|
|
if (needsTransparencySecurityCheck || needsVisibilitySecurityCheck)
|
|
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
|
|
|
|
// find out if the field type is one of the following: Primitive, Enum or Pointer
|
|
Type fieldType = FieldType;
|
|
if (fieldType.IsPointer || fieldType.IsEnum || fieldType.IsPrimitive)
|
|
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_FIELD_SPECIAL_CAST;
|
|
}
|
|
|
|
#if FEATURE_APPX
|
|
if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
|
|
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
|
|
#endif // FEATURE_APPX
|
|
|
|
// must be last to avoid threading problems
|
|
m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
|
|
}
|
|
|
|
return m_invocationFlags;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
private RuntimeAssembly GetRuntimeAssembly() { return m_declaringType.GetRuntimeAssembly(); }
|
|
|
|
#region Constructor
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
internal RtFieldInfo(
|
|
RuntimeFieldHandleInternal handle, RuntimeType declaringType, RuntimeTypeCache reflectedTypeCache, BindingFlags bindingFlags)
|
|
: base(reflectedTypeCache, declaringType, bindingFlags)
|
|
{
|
|
m_fieldHandle = handle.Value;
|
|
m_fieldAttributes = RuntimeFieldHandle.GetAttributes(handle);
|
|
}
|
|
#endregion
|
|
|
|
#region Private Members
|
|
RuntimeFieldHandleInternal IRuntimeFieldInfo.Value
|
|
{
|
|
[System.Security.SecuritySafeCritical]
|
|
get
|
|
{
|
|
return new RuntimeFieldHandleInternal(m_fieldHandle);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Internal Members
|
|
internal void CheckConsistency(Object target)
|
|
{
|
|
// only test instance fields
|
|
if ((m_fieldAttributes & FieldAttributes.Static) != FieldAttributes.Static)
|
|
{
|
|
if (!m_declaringType.IsInstanceOfType(target))
|
|
{
|
|
if (target == null)
|
|
{
|
|
#if FEATURE_LEGACYNETCF
|
|
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
|
|
throw new ArgumentNullException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
|
|
else
|
|
#endif
|
|
throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentException(
|
|
String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_FieldDeclTarget"),
|
|
Name, m_declaringType, target.GetType()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
|
#if !FEATURE_CORECLR
|
|
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
|
#endif
|
|
internal override bool CacheEquals(object o)
|
|
{
|
|
RtFieldInfo m = o as RtFieldInfo;
|
|
|
|
if ((object)m == null)
|
|
return false;
|
|
|
|
return m.m_fieldHandle == m_fieldHandle;
|
|
}
|
|
|
|
[System.Security.SecurityCritical]
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, ref StackCrawlMark stackMark)
|
|
{
|
|
INVOCATION_FLAGS invocationFlags = InvocationFlags;
|
|
RuntimeType declaringType = DeclaringType as RuntimeType;
|
|
|
|
if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
|
|
{
|
|
if (declaringType != null && declaringType.ContainsGenericParameters)
|
|
throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
|
|
|
|
if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
|
|
throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
|
|
|
|
throw new FieldAccessException();
|
|
}
|
|
|
|
CheckConsistency(obj);
|
|
|
|
RuntimeType fieldType = (RuntimeType)FieldType;
|
|
value = fieldType.CheckValue(value, binder, culture, invokeAttr);
|
|
|
|
#region Security Check
|
|
#if FEATURE_APPX
|
|
if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
|
|
{
|
|
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_SPECIAL_FIELD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0)
|
|
PerformVisibilityCheckOnField(m_fieldHandle, obj, m_declaringType, m_fieldAttributes, (uint)m_invocationFlags);
|
|
#endregion
|
|
|
|
bool domainInitialized = false;
|
|
if (declaringType == null)
|
|
{
|
|
RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
|
|
}
|
|
else
|
|
{
|
|
domainInitialized = declaringType.DomainInitialized;
|
|
RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
|
|
declaringType.DomainInitialized = domainInitialized;
|
|
}
|
|
}
|
|
|
|
// UnsafeSetValue doesn't perform any consistency or visibility check.
|
|
// It is the caller's responsibility to ensure the operation is safe.
|
|
// When the caller needs to perform visibility checks they should call
|
|
// InternalSetValue() instead. When the caller needs to perform
|
|
// consistency checks they should call CheckConsistency() before
|
|
// calling this method.
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
internal void UnsafeSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
|
|
{
|
|
RuntimeType declaringType = DeclaringType as RuntimeType;
|
|
RuntimeType fieldType = (RuntimeType)FieldType;
|
|
value = fieldType.CheckValue(value, binder, culture, invokeAttr);
|
|
|
|
bool domainInitialized = false;
|
|
if (declaringType == null)
|
|
{
|
|
RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
|
|
}
|
|
else
|
|
{
|
|
domainInitialized = declaringType.DomainInitialized;
|
|
RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
|
|
declaringType.DomainInitialized = domainInitialized;
|
|
}
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical]
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
internal Object InternalGetValue(Object obj, ref StackCrawlMark stackMark)
|
|
{
|
|
INVOCATION_FLAGS invocationFlags = InvocationFlags;
|
|
RuntimeType declaringType = DeclaringType as RuntimeType;
|
|
|
|
if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
|
|
{
|
|
if (declaringType != null && DeclaringType.ContainsGenericParameters)
|
|
throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
|
|
|
|
if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
|
|
throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
|
|
|
|
throw new FieldAccessException();
|
|
}
|
|
|
|
CheckConsistency(obj);
|
|
|
|
#if FEATURE_APPX
|
|
if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
|
|
{
|
|
RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
|
|
if (caller != null && !caller.IsSafeForReflection())
|
|
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
|
|
}
|
|
#endif
|
|
|
|
RuntimeType fieldType = (RuntimeType)FieldType;
|
|
if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0)
|
|
PerformVisibilityCheckOnField(m_fieldHandle, obj, m_declaringType, m_fieldAttributes, (uint)(m_invocationFlags & ~INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD));
|
|
|
|
return UnsafeGetValue(obj);
|
|
}
|
|
|
|
// UnsafeGetValue doesn't perform any consistency or visibility check.
|
|
// It is the caller's responsibility to ensure the operation is safe.
|
|
// When the caller needs to perform visibility checks they should call
|
|
// InternalGetValue() instead. When the caller needs to perform
|
|
// consistency checks they should call CheckConsistency() before
|
|
// calling this method.
|
|
[System.Security.SecurityCritical]
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
internal Object UnsafeGetValue(Object obj)
|
|
{
|
|
RuntimeType declaringType = DeclaringType as RuntimeType;
|
|
|
|
RuntimeType fieldType = (RuntimeType)FieldType;
|
|
|
|
bool domainInitialized = false;
|
|
if (declaringType == null)
|
|
{
|
|
return RuntimeFieldHandle.GetValue(this, obj, fieldType, null, ref domainInitialized);
|
|
}
|
|
else
|
|
{
|
|
domainInitialized = declaringType.DomainInitialized;
|
|
object retVal = RuntimeFieldHandle.GetValue(this, obj, fieldType, declaringType, ref domainInitialized);
|
|
declaringType.DomainInitialized = domainInitialized;
|
|
return retVal;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MemberInfo Overrides
|
|
public override String Name
|
|
{
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
get
|
|
{
|
|
if (m_name == null)
|
|
m_name = RuntimeFieldHandle.GetName(this);
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.FieldName(GetRuntimeType().GetFullNameForEtw(), GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
return m_name;
|
|
}
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical]
|
|
internal override String GetFullNameForEtw()
|
|
{
|
|
if (m_name == null)
|
|
return RuntimeFieldHandle.GetName(this);
|
|
|
|
return m_name;
|
|
}
|
|
|
|
internal String FullName
|
|
{
|
|
get
|
|
{
|
|
return String.Format("{0}.{1}", DeclaringType.FullName, Name);
|
|
}
|
|
}
|
|
|
|
public override int MetadataToken
|
|
{
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
get { return RuntimeFieldHandle.GetToken(this); }
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
internal override RuntimeModule GetRuntimeModule()
|
|
{
|
|
return RuntimeTypeHandle.GetModule(RuntimeFieldHandle.GetApproxDeclaringType(this));
|
|
}
|
|
#endregion
|
|
|
|
#region FieldInfo Overrides
|
|
public override Object GetValue(Object obj)
|
|
{
|
|
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
|
|
return InternalGetValue(obj, ref stackMark);
|
|
}
|
|
|
|
public override object GetRawConstantValue() { throw new InvalidOperationException(); }
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public override Object GetValueDirect(TypedReference obj)
|
|
{
|
|
if (obj.IsNull)
|
|
throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
|
|
Contract.EndContractBlock();
|
|
|
|
unsafe
|
|
{
|
|
// Passing TypedReference by reference is easier to make correct in native code
|
|
return RuntimeFieldHandle.GetValueDirect(this, (RuntimeType)FieldType, &obj, (RuntimeType)DeclaringType);
|
|
}
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
|
|
{
|
|
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
|
|
InternalSetValue(obj, value, invokeAttr, binder, culture, ref stackMark);
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public override void SetValueDirect(TypedReference obj, Object value)
|
|
{
|
|
if (obj.IsNull)
|
|
throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
|
|
Contract.EndContractBlock();
|
|
|
|
unsafe
|
|
{
|
|
// Passing TypedReference by reference is easier to make correct in native code
|
|
RuntimeFieldHandle.SetValueDirect(this, (RuntimeType)FieldType, &obj, value, (RuntimeType)DeclaringType);
|
|
}
|
|
}
|
|
|
|
public override RuntimeFieldHandle FieldHandle
|
|
{
|
|
get
|
|
{
|
|
Type declaringType = DeclaringType;
|
|
if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
|
|
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
|
|
return new RuntimeFieldHandle(this);
|
|
}
|
|
}
|
|
|
|
internal IntPtr GetFieldHandle()
|
|
{
|
|
return m_fieldHandle;
|
|
}
|
|
|
|
public override FieldAttributes Attributes
|
|
{
|
|
get
|
|
{
|
|
return m_fieldAttributes;
|
|
}
|
|
}
|
|
|
|
public override Type FieldType
|
|
{
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
get
|
|
{
|
|
if (m_fieldType == null)
|
|
m_fieldType = new Signature(this, m_declaringType).FieldType;
|
|
|
|
return m_fieldType;
|
|
}
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
public override Type[] GetRequiredCustomModifiers()
|
|
{
|
|
return new Signature(this, m_declaringType).GetCustomModifiers(1, true);
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
public override Type[] GetOptionalCustomModifiers()
|
|
{
|
|
return new Signature(this, m_declaringType).GetCustomModifiers(1, false);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
[Serializable]
|
|
internal sealed unsafe class MdFieldInfo : RuntimeFieldInfo, ISerializable
|
|
{
|
|
#region Private Data Members
|
|
private int m_tkField;
|
|
private string m_name;
|
|
private RuntimeType m_fieldType;
|
|
private FieldAttributes m_fieldAttributes;
|
|
#endregion
|
|
|
|
#region Constructor
|
|
internal MdFieldInfo(
|
|
int tkField, FieldAttributes fieldAttributes, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeCache reflectedTypeCache, BindingFlags bindingFlags)
|
|
: base(reflectedTypeCache, declaringTypeHandle.GetRuntimeType(), bindingFlags)
|
|
{
|
|
m_tkField = tkField;
|
|
m_name = null;
|
|
m_fieldAttributes = fieldAttributes;
|
|
}
|
|
#endregion
|
|
|
|
#region Internal Members
|
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
|
internal override bool CacheEquals(object o)
|
|
{
|
|
MdFieldInfo m = o as MdFieldInfo;
|
|
|
|
if ((object)m == null)
|
|
return false;
|
|
|
|
return m.m_tkField == m_tkField &&
|
|
m_declaringType.GetTypeHandleInternal().GetModuleHandle().Equals(
|
|
m.m_declaringType.GetTypeHandleInternal().GetModuleHandle());
|
|
}
|
|
#endregion
|
|
|
|
#region MemberInfo Overrides
|
|
public override String Name
|
|
{
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
get
|
|
{
|
|
if (m_name == null)
|
|
m_name = GetRuntimeModule().MetadataImport.GetName(m_tkField).ToString();
|
|
|
|
#if !FEATURE_CORECLR
|
|
if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.DynamicTypeUsage))
|
|
{
|
|
FrameworkEventSource.Log.FieldName(GetRuntimeType().GetFullNameForEtw(), GetFullNameForEtw());
|
|
}
|
|
#endif
|
|
|
|
return m_name;
|
|
}
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical]
|
|
internal override String GetFullNameForEtw()
|
|
{
|
|
if (m_name == null)
|
|
return GetRuntimeModule().MetadataImport.GetName(m_tkField).ToString();
|
|
|
|
return m_name;
|
|
}
|
|
|
|
public override int MetadataToken { get { return m_tkField; } }
|
|
internal override RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
|
|
#endregion
|
|
|
|
#region FieldInfo Overrides
|
|
public override RuntimeFieldHandle FieldHandle { get { throw new NotSupportedException(); } }
|
|
public override FieldAttributes Attributes { get { return m_fieldAttributes; } }
|
|
|
|
public override bool IsSecurityCritical { get { return DeclaringType.IsSecurityCritical; } }
|
|
public override bool IsSecuritySafeCritical { get { return DeclaringType.IsSecuritySafeCritical; } }
|
|
public override bool IsSecurityTransparent { get { return DeclaringType.IsSecurityTransparent; } }
|
|
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public override Object GetValueDirect(TypedReference obj)
|
|
{
|
|
return GetValue(null);
|
|
}
|
|
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public override void SetValueDirect(TypedReference obj,Object value)
|
|
{
|
|
throw new FieldAccessException(Environment.GetResourceString("Acc_ReadOnly"));
|
|
}
|
|
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public unsafe override Object GetValue(Object obj)
|
|
{
|
|
return GetValue(false);
|
|
}
|
|
|
|
public unsafe override Object GetRawConstantValue() { return GetValue(true); }
|
|
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
private unsafe Object GetValue(bool raw)
|
|
{
|
|
// Cannot cache these because they could be user defined non-agile enumerations
|
|
|
|
Object value = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_tkField, FieldType.GetTypeHandleInternal(), raw);
|
|
|
|
if (value == DBNull.Value)
|
|
throw new NotSupportedException(Environment.GetResourceString("Arg_EnumLitValueNotFound"));
|
|
|
|
return value;
|
|
}
|
|
|
|
[DebuggerStepThroughAttribute]
|
|
[Diagnostics.DebuggerHidden]
|
|
public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
|
|
{
|
|
throw new FieldAccessException(Environment.GetResourceString("Acc_ReadOnly"));
|
|
}
|
|
|
|
public override Type FieldType
|
|
{
|
|
[System.Security.SecuritySafeCritical] // auto-generated
|
|
get
|
|
{
|
|
if (m_fieldType == null)
|
|
{
|
|
ConstArray fieldMarshal = GetRuntimeModule().MetadataImport.GetSigOfFieldDef(m_tkField);
|
|
|
|
m_fieldType = new Signature(fieldMarshal.Signature.ToPointer(),
|
|
(int)fieldMarshal.Length, m_declaringType).FieldType;
|
|
}
|
|
|
|
return m_fieldType;
|
|
}
|
|
}
|
|
|
|
public override Type[] GetRequiredCustomModifiers()
|
|
{
|
|
return EmptyArray<Type>.Value;
|
|
}
|
|
|
|
public override Type[] GetOptionalCustomModifiers()
|
|
{
|
|
return EmptyArray<Type>.Value;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
}
|