File: System\Reflection\Metadata\TypeSystem\MethodDefinition.cs
Web Access
Project: src\runtime\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.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)
        {
            _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();
            }
        }

        /// <summary>
        /// Returns a handle to the type that declares this method.
        /// </summary>
        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
    }
}