public MethodMetadataICodeElementAdapter(Method method, TypeDefinition typeDefinition, IList<TypeDescriptor> genericTypes, MetadataReader reader)
            : base(typeDefinition, genericTypes, reader)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            this.Method = method;
        }
        public Property GetPropertyProperties(int token)
        {
            // The Property's name will be stored in this array. The 1024 is a "magical number", seems like a type's name can be maximum this long. The corhlpr.h also defines a suspicious constant like this: #define MAX_CLASSNAME_LENGTH 1024
            var propertyName = new char[1024];

            var typeDefToken = 0;

            // Number of how many characters were filled in the typeName array.
            var nameLength = 0;

            // A pointer to the binary metadata signature of the property.
            var sigBlob = new IntPtr(0);

            var sigBlobLength = 0;

            // Property's flags.
            var propertyFlags = 0;

            // A flag that marks a ValueType
            var cplusTypeFlag = 0;

            // A constant string value returned by this member.
            var defaultValue = new IntPtr(0);

            var defaultValueLength = 0;

            // method token AddOn
            var methodTokenGetter = 0;

            // method token RemoveOn
            var methodTokenSetter = 0;

            var otherMethodTokens = new int[1024];

            var otherMethodTokensCount = 0;

            // Get the Property's properties.
            var hresult = this.import.GetPropertyProps(
                token,
                ref typeDefToken,
                propertyName,
                propertyName.Length,
                ref nameLength,
                ref propertyFlags,
                ref sigBlob,
                ref sigBlobLength,
                ref cplusTypeFlag,
                ref defaultValue,
                ref defaultValueLength,
                ref methodTokenSetter,
                ref methodTokenGetter,
                otherMethodTokens,
                1024,
                ref otherMethodTokensCount);
            if (hresult != 0)
            {
                Marshal.ThrowExceptionForHR(hresult);
            }

            // supress names "" & "\0";
            if (nameLength <= 1)
            {
                // return null for this, we do not need to know about empty base
                return null;
            }

            // Get the Property's name.
            var fullTypeName = new string(propertyName, 0, nameLength - 1);

            var sigBlobBytes = new byte[sigBlobLength];
            for (var byteIndex = 0; byteIndex < sigBlobLength; byteIndex++)
            {
                sigBlobBytes[byteIndex] = Marshal.ReadByte(sigBlob, byteIndex);
            }

            var defaultValueBytes = new byte[defaultValueLength];
            for (var byteIndex = 0; byteIndex < defaultValueLength; byteIndex++)
            {
                defaultValueBytes[byteIndex] = Marshal.ReadByte(defaultValue, byteIndex);
            }

            var otherMethods = new Method[otherMethodTokensCount];
            for (var otherMethodTokenIndex = 0; otherMethodTokenIndex < otherMethodTokensCount; otherMethodTokenIndex++)
            {
                otherMethods[otherMethodTokenIndex] = this.GetMethodProperties(otherMethodTokens[otherMethodTokenIndex]);
            }

            var propertyProperties = new Property
                {
                    Token = token,
                    FullName = fullTypeName,
                    Flags = (CorPropertyAttr)propertyFlags,
                    CPlusTypeFlag = (CorElementType)cplusTypeFlag,
                    DefaultValue = defaultValueBytes,
                    SignatureBlob = sigBlobBytes,
                    Getter = this.GetMethodProperties(methodTokenGetter),
                    Setter = methodTokenSetter.IsNotEmpty(CorTokenType.MethodDef) ? this.GetMethodProperties(methodTokenSetter) : null,
                    Other = otherMethods
                };

            propertyProperties.ReadSignature(this);

            return propertyProperties;
        }
        public Method GetMethodProperties(int token)
        {
            object metadataObject = null;
            if (this.metadataObjectsCache.TryGetValue(token, out metadataObject))
            {
                return (Method)metadataObject;
            }

            // The Method's name will be stored in this array. The 1024 is a "magical number", seems like a type's name can be maximum this long. The corhlpr.h also defines a suspicious constant like this: #define MAX_CLASSNAME_LENGTH 1024
            var methodName = new char[1024];

            var typeDefToken = 0;

            // Number of how many characters were filled in the typeName array.
            var nameLength = 0;

            // Method's flags.
            var attr = 0;

            // A pointer to the binary metadata signature of the Method.
            var sigBlob = new IntPtr(0);

            var sigBlobLength = 0;

            // A pointer to the relative virtual address of the Method.
            var codeRva = 0;

            var methodImplementationFlags = 0;

            // Get the Method's properties.
            var hresult = this.import.GetMethodProps(
                token,
                ref typeDefToken,
                methodName,
                methodName.Length,
                ref nameLength,
                ref attr,
                ref sigBlob,
                ref sigBlobLength,
                ref codeRva,
                ref methodImplementationFlags);
            if (hresult != 0)
            {
                Marshal.ThrowExceptionForHR(hresult);
            }

            // supress names "" & "\0";
            if (nameLength <= 1)
            {
                // return null for this, we do not need to know about empty base
                return null;
            }

            // Get the Method's name.
            var fullTypeName = new string(methodName, 0, nameLength - 1);

            var sigBlobBytes = new byte[sigBlobLength];
            for (var byteIndex = 0; byteIndex < sigBlobLength; byteIndex++)
            {
                sigBlobBytes[byteIndex] = Marshal.ReadByte(sigBlob, byteIndex);
            }

            var methodProperties = new Method
                {
                    Token = token,
                    FullName = fullTypeName,
                    Flags = (CorMethodAttr)attr,
                    SignatureBlob = sigBlobBytes,
                    CodeRva = codeRva,
                    ImplementationFlags = (CorMethodImpl)methodImplementationFlags
                };

            // read method params
            methodProperties.Params = this.EnumerateParams(methodProperties).ToArray();

            methodProperties.ReadSignature(this);

            return methodProperties;
        }
        public Event GetEventProperties(int token)
        {
            // The Event's name will be stored in this array. The 1024 is a "magical number", seems like a type's name can be maximum this long. The corhlpr.h also defines a suspicious constant like this: #define MAX_CLASSNAME_LENGTH 1024
            var eventName = new char[1024];

            var typeDefToken = 0;

            // Number of how many characters were filled in the typeName array.
            var nameLength = 0;

            // Event's flags.
            var eventFlags = 0;

            // A pointer to a TypeRef or TypeDef metadata token representing the Delegate type of the event.
            var eventTypeToken = 0;

            // method token AddOn
            var methodTokenAddOn = 0;

            // method token RemoveOn
            var methodTokenRemoveOn = 0;

            // method token Fire
            var methodTokenFire = 0;

            var otherMethodTokens = new int[1024];

            var otherMethodTokensCount = 0;

            // Get the Event's properties.
            var hresult = this.import.GetEventProps(
                token,
                ref typeDefToken,
                eventName,
                eventName.Length,
                ref nameLength,
                ref eventFlags,
                ref eventTypeToken,
                ref methodTokenAddOn,
                ref methodTokenRemoveOn,
                ref methodTokenFire,
                otherMethodTokens,
                1024,
                ref otherMethodTokensCount);
            if (hresult != 0)
            {
                Marshal.ThrowExceptionForHR(hresult);
            }

            // supress names "" & "\0";
            if (nameLength <= 1)
            {
                // return null for this, we do not need to know about empty base
                return null;
            }

            // Get the Event's name.
            var fullTypeName = new string(eventName, 0, nameLength - 1);

            var otherMethods = new Method[otherMethodTokensCount];
            for (var otherMethodTokenIndex = 0; otherMethodTokenIndex < otherMethodTokensCount; otherMethodTokenIndex++)
            {
                otherMethods[otherMethodTokenIndex] = this.GetMethodProperties(otherMethodTokens[otherMethodTokenIndex]);
            }

            var eventProperties = new Event
                {
                    Token = token,
                    FullName = fullTypeName,
                    Flags = (CorEventAttr)eventFlags,
                    Type =
                        eventTypeToken.Is(CorTokenType.TypeDef)
                            ? (object)this.GetTypeDefinitionProperties(eventTypeToken)
                            : (object)this.GetTypeReferenceProperties(eventTypeToken),
                    AddOn = this.GetMethodProperties(methodTokenAddOn),
                    RemoveOn = this.GetMethodProperties(methodTokenRemoveOn),
                    Fire = methodTokenFire.IsNotEmpty(CorTokenType.MethodDef) ? this.GetMethodProperties(methodTokenFire) : null,
                    Other = otherMethods
                };

            return eventProperties;
        }
        /// <summary>
        /// Enumerates ParamDef tokens representing Params of the specified type.
        /// 
        /// To enumerate inherited Params, the caller must explicitly walk the inheritance chain. 
        /// </summary>
        /// <param name="method"> A ReturnTypeDefinition representing the type whose Params are to be enumerated</param>
        /// <returns>the enumerator</returns>
        public IEnumerable<Param> EnumerateParams(Method method)
        {
            // Handle of the enumeration.
            var enumHandle = 0;

            // We will read maximum 10 Params at once which will be stored in this array.
            var @params = new int[10];

            // Number of read Params.
            var count = 0;
            var hresult = this.import.EnumParams(ref enumHandle, method.Token, @params, @params.Length, ref count);
            if (hresult != 0)
            {
                Marshal.ThrowExceptionForHR(hresult);
            }

            // Continue reading Params' while the Params array contains any new Param.
            while (count > 0)
            {
                for (uint paramsIndex = 0; paramsIndex < count; paramsIndex++)
                {
                    yield return this.GetParamProperties(@params[paramsIndex]);
                }

                hresult = this.import.EnumParams(ref enumHandle, method.Token, @params, @params.Length, ref count);
                if (hresult != 0)
                {
                    Marshal.ThrowExceptionForHR(hresult);
                }
            }

            this.import.CloseEnum(enumHandle);
        }