File: System\Reflection\Metadata\TypeSystem\MethodDefinition.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 MethodDefinition
    {
        private readonly MetadataReader _reader;
 
        // Workaround: JIT doesn't generate good code for nested structures, so use RowId.
        private readonly uint _treatmentAndRowId;
 
        internal MethodDefinition(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 MethodDefTreatment Treatment
        {
            get { return (MethodDefTreatment)(_treatmentAndRowId >> TokenTypeIds.RowIdBitCount); }
        }
 
        private MethodDefinitionHandle Handle
        {
            get { return MethodDefinitionHandle.FromRowId(RowId); }
        }
 
        public StringHandle Name
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MethodDefTable.GetName(Handle);
                }
 
                return GetProjectedName();
            }
        }
 
        public BlobHandle Signature
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MethodDefTable.GetSignature(Handle);
                }
 
                return GetProjectedSignature();
            }
        }
 
        public MethodSignature<TType> DecodeSignature<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);
        }
 
        public int RelativeVirtualAddress
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MethodDefTable.GetRva(Handle);
                }
 
                return GetProjectedRelativeVirtualAddress();
            }
        }
 
        public MethodAttributes Attributes
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MethodDefTable.GetFlags(Handle);
                }
 
                return GetProjectedFlags();
            }
        }
 
        public MethodImplAttributes ImplAttributes
        {
            get
            {
                if (Treatment == 0)
                {
                    return _reader.MethodDefTable.GetImplFlags(Handle);
                }
 
                return GetProjectedImplFlags();
            }
        }
 
        public TypeDefinitionHandle GetDeclaringType()
        {
            return _reader.GetDeclaringType(Handle);
        }
 
        public ParameterHandleCollection GetParameters()
        {
            return new ParameterHandleCollection(_reader, Handle);
        }
 
        public GenericParameterHandleCollection GetGenericParameters()
        {
            return _reader.GenericParamTable.FindGenericParametersForMethod(Handle);
        }
 
        public MethodImport GetImport()
        {
            int implMapRid = _reader.ImplMapTable.FindImplForMethod(Handle);
            if (implMapRid == 0)
            {
                return default(MethodImport);
            }
 
            return _reader.ImplMapTable.GetImport(implMapRid);
        }
 
        public CustomAttributeHandleCollection GetCustomAttributes()
        {
            return new CustomAttributeHandleCollection(_reader, Handle);
        }
 
        public DeclarativeSecurityAttributeHandleCollection GetDeclarativeSecurityAttributes()
        {
            return new DeclarativeSecurityAttributeHandleCollection(_reader, Handle);
        }
 
#region Projections
 
        private StringHandle GetProjectedName()
        {
            if ((Treatment & MethodDefTreatment.KindMask) == MethodDefTreatment.DisposeMethod)
            {
                return StringHandle.FromVirtualIndex(StringHandle.VirtualIndex.Dispose);
            }
 
            return _reader.MethodDefTable.GetName(Handle);
        }
 
        private MethodAttributes GetProjectedFlags()
        {
            MethodAttributes flags = _reader.MethodDefTable.GetFlags(Handle);
            MethodDefTreatment treatment = Treatment;
 
            if ((treatment & MethodDefTreatment.KindMask) == MethodDefTreatment.HiddenInterfaceImplementation)
            {
                flags = (flags & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Private;
            }
 
            if ((treatment & MethodDefTreatment.MarkAbstractFlag) != 0)
            {
                flags |= MethodAttributes.Abstract;
            }
 
            if ((treatment & MethodDefTreatment.MarkPublicFlag) != 0)
            {
                flags = (flags & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Public;
            }
 
 
            return flags | MethodAttributes.HideBySig;
        }
 
        private MethodImplAttributes GetProjectedImplFlags()
        {
            MethodImplAttributes flags = _reader.MethodDefTable.GetImplFlags(Handle);
 
            switch (Treatment & MethodDefTreatment.KindMask)
            {
                case MethodDefTreatment.DelegateMethod:
                    flags |= MethodImplAttributes.Runtime;
                    break;
 
                case MethodDefTreatment.DisposeMethod:
                case MethodDefTreatment.AttributeMethod:
                case MethodDefTreatment.InterfaceMethod:
                case MethodDefTreatment.HiddenInterfaceImplementation:
                case MethodDefTreatment.Other:
                    flags |= MethodImplAttributes.Runtime | MethodImplAttributes.InternalCall;
                    break;
            }
 
            return flags;
        }
 
        private BlobHandle GetProjectedSignature()
        {
            return _reader.MethodDefTable.GetSignature(Handle);
        }
 
        private static int GetProjectedRelativeVirtualAddress()
        {
            return 0;
        }
#endregion
    }
}