File: src\System\Reflection\MdFieldInfo.cs
Web Access
Project: src\src\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Globalization;
using System.Reflection.Metadata;
using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
 
namespace System.Reflection
{
    internal sealed unsafe class MdFieldInfo : RuntimeFieldInfo
    {
        #region Private Data Members
        private readonly int m_tkField;
        private string? m_name;
        private RuntimeType? m_fieldType;
        private readonly 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
        internal override bool CacheEquals(object? o)
        {
            return
                o is MdFieldInfo m &&
                m.m_tkField == m_tkField &&
                ReferenceEquals(m_declaringType, m.m_declaringType);
        }
        #endregion
 
        #region MemberInfo Overrides
        public override string Name => m_name ??= GetRuntimeModule().MetadataImport.GetName(m_tkField).ToString();
 
        public override int MetadataToken => m_tkField;
        internal override RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
 
        public override bool Equals(object? obj) =>
            ReferenceEquals(this, obj) ||
            (MetadataUpdater.IsSupported &&
                obj is MdFieldInfo fi &&
                fi.m_tkField == m_tkField &&
                ReferenceEquals(fi.m_declaringType, m_declaringType) &&
                ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));
 
        public override int GetHashCode() =>
            HashCode.Combine(m_tkField.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
        #endregion
 
        #region FieldInfo Overrides
        public override RuntimeFieldHandle FieldHandle => throw new NotSupportedException();
        public override FieldAttributes Attributes => m_fieldAttributes;
 
        public override bool IsSecurityCritical => DeclaringType!.IsSecurityCritical;
        public override bool IsSecuritySafeCritical => DeclaringType!.IsSecuritySafeCritical;
        public override bool IsSecurityTransparent => DeclaringType!.IsSecurityTransparent;
 
        [DebuggerStepThrough]
        [DebuggerHidden]
        public override object? GetValueDirect(TypedReference obj)
        {
            return GetValue(null);
        }
 
        [DebuggerStepThrough]
        [DebuggerHidden]
        public override void SetValueDirect(TypedReference obj, object value)
        {
            throw new FieldAccessException(SR.Acc_ReadOnly);
        }
 
        [DebuggerStepThrough]
        [DebuggerHidden]
        public override object? GetValue(object? obj)
        {
            return GetValue(false);
        }
 
        public override object? GetRawConstantValue() { return GetValue(true); }
 
        private 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.TypeHandle, raw);
 
            if (value == DBNull.Value)
                throw new NotSupportedException(SR.Arg_EnumLitValueNotFound);
 
            return value;
        }
 
        [DebuggerStepThrough]
        [DebuggerHidden]
        public override void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, CultureInfo? culture)
        {
            throw new FieldAccessException(SR.Acc_ReadOnly);
        }
 
        public override Type FieldType
        {
            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 Type.EmptyTypes;
        }
 
        public override Type[] GetOptionalCustomModifiers()
        {
            return Type.EmptyTypes;
        }
 
        #endregion
    }
}