File: System\Reflection\Metadata\TypeSystem\MemberReference.cs
Web Access
Project: src\src\libraries\System.Reflection.Metadata\src\System.Reflection.Metadata.csproj (System.Reflection.Metadata)
// 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.Reflection.Metadata.Ecma335;
 
namespace System.Reflection.Metadata
{
    public readonly struct MemberReference
    {
        private readonly MetadataReader _reader;
 
        // Workaround: JIT doesn't generate good code for nested structures, so use RowId.
        private readonly uint _treatmentAndRowId;
 
        internal MemberReference(MetadataReader reader, uint treatmentAndRowId)
        {
            Debug.Assert(reader != null);
            Debug.Assert(treatmentAndRowId != 0);
 
            _reader = reader;
            _treatmentAndRowId = treatmentAndRowId;
        }
 
        private int RowId
        {
            get { return (int)(_treatmentAndRowId & TokenTypeIds.RIDMask); }
        }
 
        private MemberRefTreatment Treatment
        {
            get { return (MemberRefTreatment)(_treatmentAndRowId >> TokenTypeIds.RowIdBitCount); }
        }
 
        private MemberReferenceHandle Handle
        {
            get { return MemberReferenceHandle.FromRowId(RowId); }
        }
 
        /// <summary>
        /// MethodDef, ModuleRef,TypeDef, TypeRef, or TypeSpec handle.
        /// </summary>
        public EntityHandle Parent
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MemberRefTable.GetClass(Handle);
                }
 
                return GetProjectedParent();
            }
        }
 
        public StringHandle Name
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MemberRefTable.GetName(Handle);
                }
 
                return GetProjectedName();
            }
        }
 
        /// <summary>
        /// Gets a handle to the signature blob.
        /// </summary>
        public BlobHandle Signature
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MemberRefTable.GetSignature(Handle);
                }
 
                return GetProjectedSignature();
            }
        }
 
        public TType DecodeFieldSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
        {
            var decoder = new SignatureDecoder<TType, TGenericContext>(provider, _reader, genericContext);
            var blobReader = _reader.GetBlobReader(Signature);
            return decoder.DecodeFieldSignature(ref blobReader);
        }
 
        public MethodSignature<TType> DecodeMethodSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
        {
            var decoder = new SignatureDecoder<TType, TGenericContext>(provider, _reader, genericContext);
            var blobReader = _reader.GetBlobReader(Signature);
            return decoder.DecodeMethodSignature(ref blobReader);
        }
 
        /// <summary>
        /// Determines if the member reference is to a method or field.
        /// </summary>
        /// <exception cref="BadImageFormatException">The member reference signature is invalid.</exception>
        public MemberReferenceKind GetKind()
        {
            BlobReader blobReader = _reader.GetBlobReader(this.Signature);
            SignatureHeader header = blobReader.ReadSignatureHeader();
 
            return header.Kind switch
            {
                SignatureKind.Method => MemberReferenceKind.Method,
                SignatureKind.Field => MemberReferenceKind.Field,
                _ => throw new BadImageFormatException(),
            };
        }
 
        public CustomAttributeHandleCollection GetCustomAttributes()
        {
            return new CustomAttributeHandleCollection(_reader, Handle);
        }
 
#region Projections
 
        private EntityHandle GetProjectedParent()
        {
            // no change
            return _reader.MemberRefTable.GetClass(Handle);
        }
 
        private StringHandle GetProjectedName()
        {
            if (Treatment == MemberRefTreatment.Dispose)
            {
                return StringHandle.FromVirtualIndex(StringHandle.VirtualIndex.Dispose);
            }
 
            return _reader.MemberRefTable.GetName(Handle);
        }
 
        private BlobHandle GetProjectedSignature()
        {
            // no change
            return _reader.MemberRefTable.GetSignature(Handle);
        }
#endregion
    }
}