File: system\reflection\customattribute.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// <OWNER>Microsoft</OWNER>
// 
 
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic;
using System.Resources;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Runtime.ConstrainedExecution;
using System.Runtime.Versioning;
using System.Diagnostics.Contracts;
 
namespace System.Reflection 
{
    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    public class CustomAttributeData
    {
        #region Public Static Members
        public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo target)
        {
            if (target == null)
                throw new ArgumentNullException("target");
 
            return target.GetCustomAttributesData();
        }
 
        public static IList<CustomAttributeData> GetCustomAttributes(Module target)
        {
            if (target == null)
                throw new ArgumentNullException("target");
            Contract.EndContractBlock();
 
            return target.GetCustomAttributesData();
        }
 
        public static IList<CustomAttributeData> GetCustomAttributes(Assembly target)
        {
            if (target == null)
                throw new ArgumentNullException("target");
            Contract.EndContractBlock();
 
            return target.GetCustomAttributesData();
        }
 
        public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo target)
        {
            if (target == null)
                throw new ArgumentNullException("target");
            Contract.EndContractBlock();
 
            return target.GetCustomAttributesData();
        }
        #endregion
 
        #region Internal Static Members
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeType target)
        {
            Contract.Assert(target != null);
 
            IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
 
            int pcaCount = 0;
            Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeType)target, typeof(object) as RuntimeType, true, out pcaCount);
 
            if (pcaCount == 0)
                return cad;
 
            CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
            cad.CopyTo(pca, pcaCount);
            for (int i = 0; i < pcaCount; i++)
            {
                pca[i] = new CustomAttributeData(a[i]);
            }
 
            return Array.AsReadOnly(pca);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeFieldInfo target)
        {
            Contract.Assert(target != null);
 
            IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
 
            int pcaCount = 0;
            Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeFieldInfo)target, typeof(object) as RuntimeType, out pcaCount);
 
            if (pcaCount == 0)
                return cad;
 
            CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
            cad.CopyTo(pca, pcaCount);
            for (int i = 0; i < pcaCount; i++)
            {
                pca[i] = new CustomAttributeData(a[i]);
            }
 
            return Array.AsReadOnly(pca);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeMethodInfo target)
        {
            Contract.Assert(target != null);
 
            IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
 
            int pcaCount = 0;
            Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeMethodInfo)target, typeof(object) as RuntimeType, true, out pcaCount);
 
            if (pcaCount == 0)
                return cad;
 
            CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
            cad.CopyTo(pca, pcaCount);
            for (int i = 0; i < pcaCount; i++)
            {
                pca[i] = new CustomAttributeData(a[i]);
            }
 
            return Array.AsReadOnly(pca);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeConstructorInfo target)
        {
            Contract.Assert(target != null);
 
            return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeEventInfo target)
        {
            Contract.Assert(target != null);
 
            return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimePropertyInfo target)
        {
            Contract.Assert(target != null);
 
            return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeModule target)
        {
            Contract.Assert(target != null);
 
            if (target.IsResource())
                return new List<CustomAttributeData>();
 
            return GetCustomAttributes(target, target.MetadataToken);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeAssembly target)
        {
            Contract.Assert(target != null);
 
            IList<CustomAttributeData> cad = GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target.GetNativeHandle()));
 
            int pcaCount = 0;
            Attribute[] a = PseudoCustomAttribute.GetCustomAttributes(target, typeof(object) as RuntimeType, false, out pcaCount);
 
            if (pcaCount == 0)
                return cad;
 
            CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
            cad.CopyTo(pca, pcaCount);
            for (int i = 0; i < pcaCount; i++)
            {
                pca[i] = new CustomAttributeData(a[i]);
            }
 
            return Array.AsReadOnly(pca);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeParameterInfo target)
        {
            Contract.Assert(target != null);
 
            IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
 
            int pcaCount = 0;
            Attribute[] a = PseudoCustomAttribute.GetCustomAttributes(target, typeof(object) as RuntimeType, out pcaCount);
 
            if (pcaCount == 0)
                return cad;
 
            CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
            cad.CopyTo(pca, pcaCount);
            for (int i = 0; i < pcaCount; i++)
                pca[i] = new CustomAttributeData(a[i]);
 
            return Array.AsReadOnly(pca);
        }
        #endregion
 
        #region Private Static Methods
        private static CustomAttributeEncoding TypeToCustomAttributeEncoding(RuntimeType type)
        {
            if (type == (RuntimeType)typeof(int))
                return CustomAttributeEncoding.Int32;
 
            if (type.IsEnum)
                return CustomAttributeEncoding.Enum;
 
            if (type == (RuntimeType)typeof(string))
                return CustomAttributeEncoding.String;
 
            if (type == (RuntimeType)typeof(Type))
                return CustomAttributeEncoding.Type;
 
            if (type == (RuntimeType)typeof(object))
                return CustomAttributeEncoding.Object;
 
            if (type.IsArray)
                return CustomAttributeEncoding.Array;
 
            if (type == (RuntimeType)typeof(char))
                return CustomAttributeEncoding.Char;
 
            if (type == (RuntimeType)typeof(bool))
                return CustomAttributeEncoding.Boolean;
 
            if (type == (RuntimeType)typeof(byte))
                return CustomAttributeEncoding.Byte;
 
            if (type == (RuntimeType)typeof(sbyte))
                return CustomAttributeEncoding.SByte;
 
            if (type == (RuntimeType)typeof(short))
                return CustomAttributeEncoding.Int16;
 
            if (type == (RuntimeType)typeof(ushort))
                return CustomAttributeEncoding.UInt16;
 
            if (type == (RuntimeType)typeof(uint))
                return CustomAttributeEncoding.UInt32;
 
            if (type == (RuntimeType)typeof(long))
                return CustomAttributeEncoding.Int64;
 
            if (type == (RuntimeType)typeof(ulong))
                return CustomAttributeEncoding.UInt64;
 
            if (type == (RuntimeType)typeof(float))
                return CustomAttributeEncoding.Float;
 
            if (type == (RuntimeType)typeof(double))
                return CustomAttributeEncoding.Double;
 
            // System.Enum is neither an Enum nor a Class
            if (type == (RuntimeType)typeof(Enum))
                return CustomAttributeEncoding.Object;
 
            if (type.IsClass)
                return CustomAttributeEncoding.Object;
 
            if (type.IsInterface)
                return CustomAttributeEncoding.Object;
 
            if (type.IsValueType)
                return CustomAttributeEncoding.Undefined;
 
            throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKindOfTypeForCA"), "type");
        }
        private static CustomAttributeType InitCustomAttributeType(RuntimeType parameterType)
        {
            CustomAttributeEncoding encodedType = CustomAttributeData.TypeToCustomAttributeEncoding(parameterType);
            CustomAttributeEncoding encodedArrayType = CustomAttributeEncoding.Undefined;
            CustomAttributeEncoding encodedEnumType = CustomAttributeEncoding.Undefined;
            string enumName = null;
 
            if (encodedType == CustomAttributeEncoding.Array)
            {
                parameterType = (RuntimeType)parameterType.GetElementType();
                encodedArrayType = CustomAttributeData.TypeToCustomAttributeEncoding(parameterType);
            }
 
            if (encodedType == CustomAttributeEncoding.Enum || encodedArrayType == CustomAttributeEncoding.Enum)
            {
                encodedEnumType = TypeToCustomAttributeEncoding((RuntimeType)Enum.GetUnderlyingType(parameterType));
                enumName = parameterType.AssemblyQualifiedName;
            }
 
            return new CustomAttributeType(encodedType, encodedArrayType, encodedEnumType, enumName);
        }
        [System.Security.SecurityCritical]  // auto-generated
        private static IList<CustomAttributeData> GetCustomAttributes(RuntimeModule module, int tkTarget)
        {
            CustomAttributeRecord[] records = GetCustomAttributeRecords(module, tkTarget);
 
            CustomAttributeData[] customAttributes = new CustomAttributeData[records.Length];
            for (int i = 0; i < records.Length; i++)
                customAttributes[i] = new CustomAttributeData(module, records[i]);
 
            return Array.AsReadOnly(customAttributes);
        } 
        #endregion 
 
        #region Internal Static Members
        [System.Security.SecurityCritical]  // auto-generated
        internal unsafe static CustomAttributeRecord[] GetCustomAttributeRecords(RuntimeModule module, int targetToken)
        {
            MetadataImport scope = module.MetadataImport;
 
            MetadataEnumResult tkCustomAttributeTokens;
            scope.EnumCustomAttributes(targetToken, out tkCustomAttributeTokens);
 
            CustomAttributeRecord[] records = new CustomAttributeRecord[tkCustomAttributeTokens.Length];
 
            for (int i = 0; i < records.Length; i++)
            {
                scope.GetCustomAttributeProps(
                    tkCustomAttributeTokens[i], out records[i].tkCtor.Value, out records[i].blob);
            }
 
            return records;
        }
 
        internal static CustomAttributeTypedArgument Filter(IList<CustomAttributeData> attrs, Type caType, int parameter)
        {
            for (int i = 0; i < attrs.Count; i++)
            {
                if (attrs[i].Constructor.DeclaringType == caType)
                {
                    return attrs[i].ConstructorArguments[parameter];
                }
            }
 
            return new CustomAttributeTypedArgument();
        }
        #endregion
 
        #region Private Data Members
        private ConstructorInfo m_ctor;
        private RuntimeModule m_scope;
        private MemberInfo[] m_members;
        private CustomAttributeCtorParameter[] m_ctorParams;
        private CustomAttributeNamedParameter[] m_namedParams;
        private IList<CustomAttributeTypedArgument> m_typedCtorArgs;
        private IList<CustomAttributeNamedArgument> m_namedArgs;
        #endregion
 
        #region Constructor
        protected CustomAttributeData()
        {
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        private CustomAttributeData(RuntimeModule scope, CustomAttributeRecord caRecord)
        {
            m_scope = scope;
            m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(scope, caRecord.tkCtor);
 
            ParameterInfo[] parameters = m_ctor.GetParametersNoCopy();            
            m_ctorParams = new CustomAttributeCtorParameter[parameters.Length];
            for (int i = 0; i < parameters.Length; i++)
                m_ctorParams[i] = new CustomAttributeCtorParameter(InitCustomAttributeType((RuntimeType)parameters[i].ParameterType));
 
            FieldInfo[] fields = m_ctor.DeclaringType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            PropertyInfo[] properties = m_ctor.DeclaringType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            m_namedParams = new CustomAttributeNamedParameter[properties.Length + fields.Length];
            for (int i = 0; i < fields.Length; i++)
                m_namedParams[i] = new CustomAttributeNamedParameter(
                    fields[i].Name, CustomAttributeEncoding.Field, InitCustomAttributeType((RuntimeType)fields[i].FieldType));
            for (int i = 0; i < properties.Length; i++)
                m_namedParams[i + fields.Length] = new CustomAttributeNamedParameter(
                    properties[i].Name, CustomAttributeEncoding.Property, InitCustomAttributeType((RuntimeType)properties[i].PropertyType));
 
            m_members = new MemberInfo[fields.Length + properties.Length];
            fields.CopyTo(m_members, 0);
            properties.CopyTo(m_members, fields.Length);
 
            CustomAttributeEncodedArgument.ParseAttributeArguments(caRecord.blob, ref m_ctorParams, ref m_namedParams, m_scope);
        }
        #endregion
 
        #region Pseudo Custom Attribute Constructor
        internal CustomAttributeData(Attribute attribute)
        {
            if (attribute is DllImportAttribute)
                Init((DllImportAttribute)attribute);
            else if (attribute is FieldOffsetAttribute)
                Init((FieldOffsetAttribute)attribute);
            else if (attribute is MarshalAsAttribute)
                Init((MarshalAsAttribute)attribute);
            else if (attribute is TypeForwardedToAttribute)
                Init((TypeForwardedToAttribute)attribute);
            else
                Init(attribute);
        }
        private void Init(DllImportAttribute dllImport)
        {
            Type type = typeof(DllImportAttribute);
            m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
            m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[]
            {
                new CustomAttributeTypedArgument(dllImport.Value),
            });
 
            m_namedArgs = Array.AsReadOnly(new CustomAttributeNamedArgument[]
            {
                new CustomAttributeNamedArgument(type.GetField("EntryPoint"), dllImport.EntryPoint),
                new CustomAttributeNamedArgument(type.GetField("CharSet"), dllImport.CharSet),
                new CustomAttributeNamedArgument(type.GetField("ExactSpelling"), dllImport.ExactSpelling),
                new CustomAttributeNamedArgument(type.GetField("SetLastError"), dllImport.SetLastError),
                new CustomAttributeNamedArgument(type.GetField("PreserveSig"), dllImport.PreserveSig),
                new CustomAttributeNamedArgument(type.GetField("CallingConvention"), dllImport.CallingConvention),
                new CustomAttributeNamedArgument(type.GetField("BestFitMapping"), dllImport.BestFitMapping),
                new CustomAttributeNamedArgument(type.GetField("ThrowOnUnmappableChar"), dllImport.ThrowOnUnmappableChar)
 
            });
        }
        private void Init(FieldOffsetAttribute fieldOffset)
        {
            m_ctor = typeof(FieldOffsetAttribute).GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
            m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[] {
                new CustomAttributeTypedArgument(fieldOffset.Value)
            });
            m_namedArgs = Array.AsReadOnly(new CustomAttributeNamedArgument[0]);
        }
        private void Init(MarshalAsAttribute marshalAs)
        {
            Type type = typeof(MarshalAsAttribute);
            m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
            m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[]
            {
                new CustomAttributeTypedArgument(marshalAs.Value),
            });
 
            int i = 3; // ArraySubType, SizeParamIndex, SizeConst
            if (marshalAs.MarshalType != null) i++;
            if (marshalAs.MarshalTypeRef != null) i++;
            if (marshalAs.MarshalCookie != null) i++;
            i++; // IidParameterIndex
            i++; // SafeArraySubType
            if (marshalAs.SafeArrayUserDefinedSubType != null) i++;
            CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[i];
 
            // For compatibility with previous runtimes, we always include the following 5 attributes, regardless
            // of if they apply to the UnmanagedType being marshaled or not.
            i = 0;
            namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("ArraySubType"), marshalAs.ArraySubType);
            namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SizeParamIndex"), marshalAs.SizeParamIndex);
            namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SizeConst"), marshalAs.SizeConst);
            namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("IidParameterIndex"), marshalAs.IidParameterIndex);
            namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArraySubType"), marshalAs.SafeArraySubType);
            if (marshalAs.MarshalType != null)
                namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalType"), marshalAs.MarshalType);
            if (marshalAs.MarshalTypeRef != null)
                namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalTypeRef"), marshalAs.MarshalTypeRef);
            if (marshalAs.MarshalCookie != null)
                namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalCookie"), marshalAs.MarshalCookie);
            if (marshalAs.SafeArrayUserDefinedSubType != null)
                namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArrayUserDefinedSubType"), marshalAs.SafeArrayUserDefinedSubType);
 
            m_namedArgs = Array.AsReadOnly(namedArgs);
        }
        private void Init(TypeForwardedToAttribute forwardedTo)
        {
            Type type = typeof(TypeForwardedToAttribute);
 
            Type[] sig = new Type[] { typeof(Type) };
            m_ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, sig, null);
 
            CustomAttributeTypedArgument[] typedArgs = new CustomAttributeTypedArgument[1];
            typedArgs[0] = new CustomAttributeTypedArgument(typeof(Type), forwardedTo.Destination);
            m_typedCtorArgs = Array.AsReadOnly(typedArgs);
 
            CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[0];
            m_namedArgs = Array.AsReadOnly(namedArgs);
        }
        private void Init(object pca)
        {
            m_ctor = pca.GetType().GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
            m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[0]);
            m_namedArgs = Array.AsReadOnly(new CustomAttributeNamedArgument[0]);
        }
        #endregion
 
        #region Object Override
        public override string ToString()
        {
            string ctorArgs = "";
            for (int i = 0; i < ConstructorArguments.Count; i ++)
                ctorArgs += String.Format(CultureInfo.CurrentCulture, i == 0 ? "{0}" : ", {0}", ConstructorArguments[i]);
 
            string namedArgs = "";
            for (int i = 0; i < NamedArguments.Count; i ++)
                namedArgs += String.Format(CultureInfo.CurrentCulture, i == 0 && ctorArgs.Length == 0 ? "{0}" : ", {0}", NamedArguments[i]);
 
            return String.Format(CultureInfo.CurrentCulture, "[{0}({1}{2})]", Constructor.DeclaringType.FullName, ctorArgs, namedArgs);
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public override bool Equals(object obj)
        {
            return obj == (object)this;
        }
        #endregion
 
        #region Public Members
        public Type AttributeType { get { return Constructor.DeclaringType; } }
 
        [System.Runtime.InteropServices.ComVisible(true)]
        public virtual ConstructorInfo Constructor { get { return m_ctor; } }
        
        [System.Runtime.InteropServices.ComVisible(true)]
        public virtual IList<CustomAttributeTypedArgument> ConstructorArguments
        {
            get
            {
                if (m_typedCtorArgs == null)
                {
                    CustomAttributeTypedArgument[] typedCtorArgs = new CustomAttributeTypedArgument[m_ctorParams.Length];
 
                    for (int i = 0; i < typedCtorArgs.Length; i++)
                    {
                        CustomAttributeEncodedArgument encodedArg = m_ctorParams[i].CustomAttributeEncodedArgument;
 
                        typedCtorArgs[i] = new CustomAttributeTypedArgument(m_scope, m_ctorParams[i].CustomAttributeEncodedArgument);
                    }
 
                    m_typedCtorArgs = Array.AsReadOnly(typedCtorArgs);
                }
 
                return m_typedCtorArgs;
            }
        }
 
        public virtual IList<CustomAttributeNamedArgument> NamedArguments
        {
            get
            {
                if (m_namedArgs == null)
                {
                    if (m_namedParams == null)
                        return null;
 
                    int cNamedArgs = 0;
                    for (int i = 0; i < m_namedParams.Length; i++)
                    {
                        if (m_namedParams[i].EncodedArgument.CustomAttributeType.EncodedType != CustomAttributeEncoding.Undefined)
                            cNamedArgs++;
                    }
 
                    CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[cNamedArgs];
 
                    for (int i = 0, j = 0; i < m_namedParams.Length; i++)
                    {
                        if (m_namedParams[i].EncodedArgument.CustomAttributeType.EncodedType != CustomAttributeEncoding.Undefined)
                            namedArgs[j++] = new CustomAttributeNamedArgument(
                                m_members[i], new CustomAttributeTypedArgument(m_scope, m_namedParams[i].EncodedArgument));
                    }
 
                    m_namedArgs = Array.AsReadOnly(namedArgs);
                }
 
                return m_namedArgs;
            }
        }
        #endregion
    }
 
    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    public struct CustomAttributeNamedArgument
    {
        #region Public Static Members
        public static bool operator ==(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right)
        {
            return left.Equals(right);
        }
        public static bool operator !=(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right)
        {
            return !left.Equals(right);
        }
        #endregion
 
        #region Private Data Members
        private MemberInfo m_memberInfo;
        private CustomAttributeTypedArgument m_value;
        #endregion
 
        #region Constructor
        public CustomAttributeNamedArgument(MemberInfo memberInfo, object value)
        {
            if (memberInfo == null)
                throw new ArgumentNullException("memberInfo");
 
            Type type = null;
            FieldInfo field = memberInfo as FieldInfo;
            PropertyInfo property = memberInfo as PropertyInfo;
 
            if (field != null)
                type = field.FieldType;
            else if (property != null)
                type = property.PropertyType;
            else
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidMemberForNamedArgument"));
 
            m_memberInfo = memberInfo;
            m_value = new CustomAttributeTypedArgument(type, value);
        }
 
        public CustomAttributeNamedArgument(MemberInfo memberInfo, CustomAttributeTypedArgument typedArgument)
        {
            if (memberInfo == null)
                throw new ArgumentNullException("memberInfo");
 
            m_memberInfo = memberInfo;
            m_value = typedArgument;
        }
        #endregion
 
        #region Object Override
        public override string ToString()
        {
            if (m_memberInfo == null)
                return base.ToString();
 
            return String.Format(CultureInfo.CurrentCulture, "{0} = {1}", MemberInfo.Name, TypedValue.ToString(ArgumentType != typeof(object))); 
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public override bool Equals(object obj)
        {
            return obj == (object)this;
        }
        #endregion
 
        #region Internal Members
        internal Type ArgumentType 
        { 
            get 
            { 
                return m_memberInfo is FieldInfo ? 
                    ((FieldInfo)m_memberInfo).FieldType : 
                    ((PropertyInfo)m_memberInfo).PropertyType; 
            } 
        }
        #endregion
 
        #region Public Members
        public MemberInfo MemberInfo { get { return m_memberInfo; } }
        public CustomAttributeTypedArgument TypedValue { get { return m_value; } }
        public string MemberName { get { return MemberInfo.Name; } }
        public bool IsField { get { return MemberInfo is FieldInfo; } }
        #endregion
 
    }
 
    [Serializable]
    [ComVisible(true)]
    public struct CustomAttributeTypedArgument
    {
        #region Public Static Members
        public static bool operator ==(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right)
        {
            return left.Equals(right);
        }
        public static bool operator !=(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right)
        {
            return !left.Equals(right);
        }
        #endregion
 
        #region Private Static Methods
        private static Type CustomAttributeEncodingToType(CustomAttributeEncoding encodedType)
        {
            switch (encodedType)
            {
                case (CustomAttributeEncoding.Enum):
                    return typeof(Enum);
 
                case (CustomAttributeEncoding.Int32):
                    return typeof(int);
 
                case (CustomAttributeEncoding.String):
                    return typeof(string);
 
                case (CustomAttributeEncoding.Type):
                    return typeof(Type);
 
                case (CustomAttributeEncoding.Array):
                    return typeof(Array);
 
                case (CustomAttributeEncoding.Char):
                    return typeof(char);
 
                case (CustomAttributeEncoding.Boolean):
                    return typeof(bool);
 
                case (CustomAttributeEncoding.SByte):
                    return typeof(sbyte);
 
                case (CustomAttributeEncoding.Byte):
                    return typeof(byte);
 
                case (CustomAttributeEncoding.Int16):
                    return typeof(short);
 
                case (CustomAttributeEncoding.UInt16):
                    return typeof(ushort);
 
                case (CustomAttributeEncoding.UInt32):
                    return typeof(uint);
 
                case (CustomAttributeEncoding.Int64):
                    return typeof(long);
 
                case (CustomAttributeEncoding.UInt64):
                    return typeof(ulong);
 
                case (CustomAttributeEncoding.Float):
                    return typeof(float);
 
                case (CustomAttributeEncoding.Double):
                    return typeof(double);
 
                case (CustomAttributeEncoding.Object):
                    return typeof(object);
 
                default :
                    throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)encodedType), "encodedType");
            }
        }
 
        [SecuritySafeCritical]
        private static object EncodedValueToRawValue(long val, CustomAttributeEncoding encodedType)
        {
            switch (encodedType)
            {
                case CustomAttributeEncoding.Boolean:
                    return (byte)val != 0;
 
                case CustomAttributeEncoding.Char:
                    return (char)val;
 
                case CustomAttributeEncoding.Byte:
                    return (byte)val;
 
                case CustomAttributeEncoding.SByte:
                    return (sbyte)val;
 
                case CustomAttributeEncoding.Int16:
                    return (short)val;
 
                case CustomAttributeEncoding.UInt16:
                    return (ushort)val;
 
                case CustomAttributeEncoding.Int32:
                    return (int)val;
 
                case CustomAttributeEncoding.UInt32:
                    return (uint)val;
 
                case CustomAttributeEncoding.Int64:
                    return (long)val;
 
                case CustomAttributeEncoding.UInt64:
                    return (ulong)val;
 
                case CustomAttributeEncoding.Float:
                    unsafe { return *(float*)&val; }
 
                case CustomAttributeEncoding.Double:
                    unsafe { return *(double*)&val; }
 
                default:
                    throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)val), "val");
            }
        }
        private static RuntimeType ResolveType(RuntimeModule scope, string typeName)
        {
            RuntimeType type = RuntimeTypeHandle.GetTypeByNameUsingCARules(typeName, scope);
 
            if (type == null)
                throw new InvalidOperationException(
                    String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_CATypeResolutionFailed"), typeName));
 
            return type;
        }
        #endregion
 
        #region Private Data Members
        private object m_value;
        private Type m_argumentType;
        #endregion
 
        #region Constructor
        public CustomAttributeTypedArgument(Type argumentType, object value)
        {
            // value can be null.
            if (argumentType == null)
                throw new ArgumentNullException("argumentType");
 
            m_value = (value == null) ? null : CanonicalizeValue(value);
            m_argumentType = argumentType;
        }
 
        public CustomAttributeTypedArgument(object value)
        {
            // value cannot be null.
            if (value == null)
                throw new ArgumentNullException("value");
 
            m_value = CanonicalizeValue(value);
            m_argumentType = value.GetType();
        }
 
        private static object CanonicalizeValue(object value)
        {
            Contract.Assert(value != null);
 
            if (value.GetType().IsEnum)
            {
                return ((Enum)value).GetValue();
            }
            return value;
        }
 
        internal CustomAttributeTypedArgument(RuntimeModule scope, CustomAttributeEncodedArgument encodedArg)
        {
            CustomAttributeEncoding encodedType = encodedArg.CustomAttributeType.EncodedType;
 
            if (encodedType == CustomAttributeEncoding.Undefined)
                throw new ArgumentException("encodedArg");
 
            else if (encodedType == CustomAttributeEncoding.Enum)
            {
                m_argumentType = ResolveType(scope, encodedArg.CustomAttributeType.EnumName);
                m_value = EncodedValueToRawValue(encodedArg.PrimitiveValue, encodedArg.CustomAttributeType.EncodedEnumType);
            }
            else if (encodedType == CustomAttributeEncoding.String)
            {
                m_argumentType = typeof(string);
                m_value = encodedArg.StringValue;
            }
            else if (encodedType == CustomAttributeEncoding.Type)
            {
                m_argumentType = typeof(Type);
                
                m_value = null;
 
                if (encodedArg.StringValue != null)
                    m_value = ResolveType(scope, encodedArg.StringValue);
            }
            else if (encodedType == CustomAttributeEncoding.Array)
            {                
                encodedType = encodedArg.CustomAttributeType.EncodedArrayType;
                Type elementType;
                
                if (encodedType == CustomAttributeEncoding.Enum)
                {
                    elementType = ResolveType(scope, encodedArg.CustomAttributeType.EnumName);
                }
                else
                {
                    elementType = CustomAttributeEncodingToType(encodedType);
                }
 
                m_argumentType = elementType.MakeArrayType();
        
                if (encodedArg.ArrayValue == null)
                {
                    m_value = null;                    
                }
                else
                {
                    CustomAttributeTypedArgument[] arrayValue = new CustomAttributeTypedArgument[encodedArg.ArrayValue.Length];
                    for (int i = 0; i < arrayValue.Length; i++)
                        arrayValue[i] = new CustomAttributeTypedArgument(scope, encodedArg.ArrayValue[i]);
 
                    m_value = Array.AsReadOnly(arrayValue);
                }
            }
            else
            {
                m_argumentType = CustomAttributeEncodingToType(encodedType);
                m_value = EncodedValueToRawValue(encodedArg.PrimitiveValue, encodedType);
            }
        }
        #endregion
 
        #region Object Overrides
        public override string ToString() { return ToString(false); }
 
        internal string ToString(bool typed)
        {
            if (m_argumentType == null)
                return base.ToString();
 
            if (ArgumentType.IsEnum)
                return String.Format(CultureInfo.CurrentCulture, typed ? "{0}" : "({1}){0}", Value, ArgumentType.FullName);
 
            else if (Value == null)
                return String.Format(CultureInfo.CurrentCulture, typed ? "null" : "({0})null", ArgumentType.Name);
 
            else if (ArgumentType == typeof(string))
                return String.Format(CultureInfo.CurrentCulture, "\"{0}\"", Value);
 
            else if (ArgumentType == typeof(char))
                return String.Format(CultureInfo.CurrentCulture, "'{0}'", Value);
 
            else if (ArgumentType == typeof(Type))
                return String.Format(CultureInfo.CurrentCulture, "typeof({0})", ((Type)Value).FullName);
 
            else if (ArgumentType.IsArray)
            {
                string result = null;
                IList<CustomAttributeTypedArgument> array = Value as IList<CustomAttributeTypedArgument>;
 
                Type elementType = ArgumentType.GetElementType();
                result = String.Format(CultureInfo.CurrentCulture, @"new {0}[{1}] {{ ", elementType.IsEnum ? elementType.FullName : elementType.Name, array.Count);
 
                for (int i = 0; i < array.Count; i++)
                    result += String.Format(CultureInfo.CurrentCulture, i == 0 ? "{0}" : ", {0}", array[i].ToString(elementType != typeof(object)));
 
                return result += " }";
            }
 
            return String.Format(CultureInfo.CurrentCulture, typed ? "{0}" : "({1}){0}", Value, ArgumentType.Name);
        }
 
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public override bool Equals(object obj)
        {
            return obj == (object)this;
        }
        #endregion
 
        #region Public Members
        public Type ArgumentType
        {
            get
            {
                return m_argumentType;
            }
        }
        public object Value 
        { 
            get 
            {
                return m_value;
            } 
        }
        #endregion
    }
 
    [Serializable]
    internal struct CustomAttributeRecord
    {
        internal ConstArray blob;
        internal MetadataToken tkCtor;
    }
 
    [Serializable]
    internal enum CustomAttributeEncoding : int
    {
        Undefined = 0,
        Boolean = CorElementType.Boolean,
        Char = CorElementType.Char,
        SByte = CorElementType.I1,
        Byte = CorElementType.U1,
        Int16 = CorElementType.I2,
        UInt16 = CorElementType.U2,
        Int32 = CorElementType.I4,
        UInt32 = CorElementType.U4,
        Int64 = CorElementType.I8,
        UInt64 = CorElementType.U8,
        Float = CorElementType.R4,
        Double = CorElementType.R8,
        String = CorElementType.String,
        Array = CorElementType.SzArray,
        Type = 0x50,
        Object = 0x51,
        Field = 0x53,
        Property = 0x54,
        Enum = 0x55
    }
 
    [Serializable]
    [StructLayout(LayoutKind.Auto)]
    internal struct CustomAttributeEncodedArgument
    { 
        #region Parser
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void ParseAttributeArguments(
            IntPtr pCa, 
            int cCa, 
            ref CustomAttributeCtorParameter[] CustomAttributeCtorParameters,
            ref CustomAttributeNamedParameter[] CustomAttributeTypedArgument,
            RuntimeAssembly assembly);
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static void ParseAttributeArguments(ConstArray attributeBlob, 
            ref CustomAttributeCtorParameter[] customAttributeCtorParameters,
            ref CustomAttributeNamedParameter[] customAttributeNamedParameters,
            RuntimeModule customAttributeModule)
        {
            if (customAttributeModule == null)
                throw new ArgumentNullException("customAttributeModule");
            Contract.EndContractBlock();
 
            Contract.Assert(customAttributeCtorParameters != null);
            Contract.Assert(customAttributeNamedParameters != null);
 
            if (customAttributeCtorParameters.Length != 0 || customAttributeNamedParameters.Length != 0)
            {
                unsafe
                {
                    ParseAttributeArguments(
                        attributeBlob.Signature,
                        (int)attributeBlob.Length,
                        ref customAttributeCtorParameters,
                        ref customAttributeNamedParameters,
                        (RuntimeAssembly)customAttributeModule.Assembly);
                }
            }
        }
        #endregion
 
        #region Private Data Members
        private long m_primitiveValue;
        private CustomAttributeEncodedArgument[] m_arrayValue;
        private string m_stringValue;
        private CustomAttributeType m_type;
        #endregion
 
        #region Public Members
        public CustomAttributeType CustomAttributeType { get { return m_type; } }
        public long PrimitiveValue { get { return m_primitiveValue; } }
        public CustomAttributeEncodedArgument[] ArrayValue { get { return m_arrayValue; } }
        public string StringValue { get { return m_stringValue; } }
        #endregion
    }
    
    [Serializable]
    [StructLayout(LayoutKind.Auto)]
    internal struct CustomAttributeNamedParameter
    {
        #region Private Data Members
        private string m_argumentName;
        private CustomAttributeEncoding m_fieldOrProperty;
        private CustomAttributeEncoding m_padding;
        private CustomAttributeType m_type;
        private CustomAttributeEncodedArgument m_encodedArgument;
        #endregion
 
        #region Constructor
        public CustomAttributeNamedParameter(string argumentName, CustomAttributeEncoding fieldOrProperty, CustomAttributeType type)
        {
            if (argumentName == null)
                throw new ArgumentNullException("argumentName");
            Contract.EndContractBlock();
 
            m_argumentName = argumentName;
            m_fieldOrProperty = fieldOrProperty;
            m_padding = fieldOrProperty;
            m_type = type;
            m_encodedArgument = new CustomAttributeEncodedArgument();
        }
        #endregion
 
        #region Public Members
        public CustomAttributeEncodedArgument EncodedArgument { get { return m_encodedArgument; } }
        #endregion
    }
    
    [Serializable]
    [StructLayout(LayoutKind.Auto)]
    internal struct CustomAttributeCtorParameter
    {
        #region Private Data Members
        private CustomAttributeType m_type;
        private CustomAttributeEncodedArgument m_encodedArgument;
        #endregion
 
        #region Constructor
        public CustomAttributeCtorParameter(CustomAttributeType type)
        {
            m_type = type;
            m_encodedArgument = new CustomAttributeEncodedArgument();
        }
        #endregion
 
        #region Public Members
        public CustomAttributeEncodedArgument CustomAttributeEncodedArgument { get { return m_encodedArgument; } }
        #endregion
    }
 
    // Note: This is a managed representation of a frame type defined in vm\frames.h; please ensure the layout remains
    // synchronized.
    [StructLayout(LayoutKind.Sequential)]
    internal struct SecurityContextFrame
    {
        IntPtr m_GSCookie;      // This is actually at a negative offset in the real frame definition
        IntPtr __VFN_table;     // This is the real start of the SecurityContextFrame
        IntPtr m_Next;
        IntPtr m_Assembly;
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        public extern void Push(RuntimeAssembly assembly);
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public extern void Pop();
    }
 
    [Serializable]
    [StructLayout(LayoutKind.Auto)]
    internal struct CustomAttributeType
    {
        #region Private Data Members
        /// The most complicated type is an enum[] in which case...
        private string m_enumName; // ...enum name
        private CustomAttributeEncoding m_encodedType; // ...array
        private CustomAttributeEncoding m_encodedEnumType; // ...enum
        private CustomAttributeEncoding m_encodedArrayType; // ...enum type
        private CustomAttributeEncoding m_padding; 
        #endregion
 
        #region Constructor
        public CustomAttributeType(CustomAttributeEncoding encodedType, CustomAttributeEncoding encodedArrayType, 
            CustomAttributeEncoding encodedEnumType, string enumName)
        {
            m_encodedType = encodedType;
            m_encodedArrayType = encodedArrayType;
            m_encodedEnumType = encodedEnumType;
            m_enumName = enumName;
            m_padding = m_encodedType; 
        }
        #endregion
 
        #region Public Members
        public CustomAttributeEncoding EncodedType { get { return m_encodedType; } }
        public CustomAttributeEncoding EncodedEnumType { get { return m_encodedEnumType; } }
        public CustomAttributeEncoding EncodedArrayType { get { return m_encodedArrayType; } }
        [System.Runtime.InteropServices.ComVisible(true)]
        public string EnumName { get { return m_enumName; } }
        #endregion
    }
 
    internal unsafe static class CustomAttribute
    {
        #region Private Data Members
        private static RuntimeType Type_RuntimeType = (RuntimeType)typeof(RuntimeType);
        private static RuntimeType Type_Type = (RuntimeType)typeof(Type);
        #endregion
 
        #region Internal Static Members
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeType type, RuntimeType caType, bool inherit)
        {
            Contract.Requires(type != null);
 
            if (type.GetElementType() != null) 
                return false;
 
            if (PseudoCustomAttribute.IsDefined(type, caType))
                return true;
 
            if (IsCustomAttributeDefined(type.GetRuntimeModule(), type.MetadataToken, caType))
                return true;
 
            if (!inherit)
                return false;
 
            type = type.BaseType as RuntimeType;
 
            while (type != null)
            {
                if (IsCustomAttributeDefined(type.GetRuntimeModule(), type.MetadataToken, caType, 0, inherit))
                    return true;
 
                type = type.BaseType as RuntimeType;
            }
 
            return false;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType, bool inherit)
        {
            Contract.Requires(method != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(method, caType))
                return true;
 
            if (IsCustomAttributeDefined(method.GetRuntimeModule(), method.MetadataToken, caType))
                return true;
 
            if (!inherit)
                return false;
 
            method = method.GetParentDefinition();
 
            while (method != null)
            {
                if (IsCustomAttributeDefined(method.GetRuntimeModule(), method.MetadataToken, caType, 0, inherit))
                    return true;
 
                method = method.GetParentDefinition();
            }
 
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType)
        {
            Contract.Requires(ctor != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(ctor, caType))
                return true;
 
            return IsCustomAttributeDefined(ctor.GetRuntimeModule(), ctor.MetadataToken, caType);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType)
        {
            Contract.Requires(property != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(property, caType))
                return true;
 
            return IsCustomAttributeDefined(property.GetRuntimeModule(), property.MetadataToken, caType);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType)
        {
            Contract.Requires(e != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(e, caType))
                return true;
 
            return IsCustomAttributeDefined(e.GetRuntimeModule(), e.MetadataToken, caType);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType)
        {
            Contract.Requires(field != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(field, caType))
                return true;
 
            return IsCustomAttributeDefined(field.GetRuntimeModule(), field.MetadataToken, caType);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType)
        {
            Contract.Requires(parameter != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(parameter, caType))
                return true;
 
            return IsCustomAttributeDefined(parameter.GetRuntimeModule(), parameter.MetadataToken, caType);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType) 
        {
            Contract.Requires(assembly != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(assembly, caType))
                return true;
 
            return IsCustomAttributeDefined(assembly.ManifestModule as RuntimeModule, RuntimeAssembly.GetToken(assembly.GetNativeHandle()), caType);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeModule module, RuntimeType caType)
        {
            Contract.Requires(module != null);
            Contract.Requires(caType != null);
 
            if (PseudoCustomAttribute.IsDefined(module, caType))
                return true;
 
            return IsCustomAttributeDefined(module, module.MetadataToken, caType);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool inherit)
        {
            Contract.Requires(type != null);
            Contract.Requires(caType != null);
 
            if (type.GetElementType() != null) 
                return (caType.IsValueType) ? EmptyArray<Object>.Value : CreateAttributeArrayHelper(caType, 0);
 
            if (type.IsGenericType && !type.IsGenericTypeDefinition)
                type = type.GetGenericTypeDefinition() as RuntimeType;
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(type, caType, true, out pcaCount);
 
            // if we are asked to go up the hierarchy chain we have to do it now and regardless of the
            // attribute usage for the specific attribute because a derived attribute may override the usage...           
            // ... however if the attribute is sealed we can rely on the attribute usage
            if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited))
            {
                object[] attributes = GetCustomAttributes(type.GetRuntimeModule(), type.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(type));
                if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
                return attributes;
            }
 
            List<object> result = new List<object>();
            bool mustBeInheritable = false;
            bool useObjectArray = (caType == null || caType.IsValueType || caType.ContainsGenericParameters);
            Type arrayType = useObjectArray ? typeof(object) : caType;
 
            while (pcaCount > 0)
                result.Add(pca[--pcaCount]);
 
            while (type != (RuntimeType)typeof(object) && type != null)
            {
                object[] attributes = GetCustomAttributes(type.GetRuntimeModule(), type.MetadataToken, 0, caType, mustBeInheritable, result, !AllowCriticalCustomAttributes(type));
                mustBeInheritable = true;
                for (int i = 0; i < attributes.Length; i++)
                    result.Add(attributes[i]);
 
                type = type.BaseType as RuntimeType;
            }
 
            object[] typedResult = CreateAttributeArrayHelper(arrayType, result.Count);
            Array.Copy(result.ToArray(), 0, typedResult, 0, result.Count);
            return typedResult;
        }
 
        private static bool AllowCriticalCustomAttributes(RuntimeType type)
        {
            if (type.IsGenericParameter) 
            {
                // Generic parameters don't have transparency state, so look at the 
                // declaring method/type. One of declaringMethod or declaringType
                // must be set.
                MethodBase declaringMethod = type.DeclaringMethod;
                if (declaringMethod != null)
                {
                    return AllowCriticalCustomAttributes(declaringMethod); 
                }
                else
                {
                    type = type.DeclaringType as RuntimeType;
                    Contract.Assert(type != null);
                }
            }
 
            return !type.IsSecurityTransparent || SpecialAllowCriticalAttributes(type);
        }
 
        private static bool SpecialAllowCriticalAttributes(RuntimeType type)
        {
            // Types participating in Type Equivalence are always transparent.
            // See TokenSecurityDescriptor::VerifySemanticDataComputed in securitymeta.cpp.
            // Because of that we allow critical attributes applied to full trust equivalent types.
            // DeclaringType is null for global methods and fields and the global type never participates in type equivalency.
 
#if FEATURE_CORECLR
            return false;
#else
            return type != null && type.Assembly.IsFullyTrusted && RuntimeTypeHandle.IsEquivalentType(type);
#endif //!FEATURE_CORECLR
        }
 
        private static bool AllowCriticalCustomAttributes(MethodBase method)
        {
            Contract.Requires(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
 
            return !method.IsSecurityTransparent ||
                SpecialAllowCriticalAttributes((RuntimeType)method.DeclaringType);
        }
 
        private static bool AllowCriticalCustomAttributes(RuntimeFieldInfo field)
        {
            return !field.IsSecurityTransparent ||
                SpecialAllowCriticalAttributes((RuntimeType)field.DeclaringType);
        }
 
        private static bool AllowCriticalCustomAttributes(RuntimeParameterInfo parameter)
        {
            // Since parameters have no transparency state, we look at the defining method instead.
            return AllowCriticalCustomAttributes(parameter.DefiningMethod);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool inherit)
        {
            Contract.Requires(method != null);
            Contract.Requires(caType != null);
 
            if (method.IsGenericMethod && !method.IsGenericMethodDefinition)
                method = method.GetGenericMethodDefinition() as RuntimeMethodInfo;
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(method, caType, true, out pcaCount);
 
            // if we are asked to go up the hierarchy chain we have to do it now and regardless of the
            // attribute usage for the specific attribute because a derived attribute may override the usage...           
            // ... however if the attribute is sealed we can rely on the attribute usage
            if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited))
            {
                object[] attributes = GetCustomAttributes(method.GetRuntimeModule(), method.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(method));
                if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
                return attributes;
            }
 
            List<object> result = new List<object>();
            bool mustBeInheritable = false;
            bool useObjectArray = (caType == null || caType.IsValueType || caType.ContainsGenericParameters);
            Type arrayType = useObjectArray ? typeof(object) : caType;
 
            while (pcaCount > 0) 
                result.Add(pca[--pcaCount]);
                
            while (method != null)
            {
                object[] attributes = GetCustomAttributes(method.GetRuntimeModule(), method.MetadataToken, 0, caType, mustBeInheritable, result, !AllowCriticalCustomAttributes(method));
                mustBeInheritable = true;
                for (int i = 0; i < attributes.Length; i++)
                    result.Add(attributes[i]);
 
                method = method.GetParentDefinition();
            }
 
            object[] typedResult = CreateAttributeArrayHelper(arrayType, result.Count);
            Array.Copy(result.ToArray(), 0, typedResult, 0, result.Count);
            return typedResult;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType)
        {
            Contract.Requires(ctor != null);
            Contract.Requires(caType != null);
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(ctor, caType, true, out pcaCount);
            object[] attributes = GetCustomAttributes(ctor.GetRuntimeModule(), ctor.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(ctor));
            if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
            return attributes;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType)
        {
            Contract.Requires(property != null);
            Contract.Requires(caType != null);
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(property, caType, out pcaCount);
            // Since properties and events have no transparency state, logically we should check the declaring types.
            // But then if someone wanted to apply critical attributes on a property/event he would need to make the type critical,
            // which would also implicitly made all the members critical.
            // So we check the containing assembly instead. If the assembly can contain critical code we allow critical attributes on properties/events.
            bool disallowCriticalCustomAttributes = property.GetRuntimeModule().GetRuntimeAssembly().IsAllSecurityTransparent();
 
            object[] attributes = GetCustomAttributes(property.GetRuntimeModule(), property.MetadataToken, pcaCount, caType, disallowCriticalCustomAttributes);
            if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
            return attributes;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType)
        {
            Contract.Requires(e != null);
            Contract.Requires(caType != null);
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(e, caType, out pcaCount);
            // Since properties and events have no transparency state, logically we should check the declaring types.
            // But then if someone wanted to apply critical attributes on a property/event he would need to make the type critical,
            // which would also implicitly made all the members critical.
            // So we check the containing assembly instead. If the assembly can contain critical code we allow critical attributes on properties/events.
            bool disallowCriticalCustomAttributes = e.GetRuntimeModule().GetRuntimeAssembly().IsAllSecurityTransparent();
            object[] attributes = GetCustomAttributes(e.GetRuntimeModule(), e.MetadataToken, pcaCount, caType, disallowCriticalCustomAttributes);
            if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
            return attributes;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType)
        {
            Contract.Requires(field != null);
            Contract.Requires(caType != null);
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(field, caType, out pcaCount);
            object[] attributes = GetCustomAttributes(field.GetRuntimeModule(), field.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(field));
            if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
            return attributes;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType)
        {
            Contract.Requires(parameter != null);
            Contract.Requires(caType != null);
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(parameter, caType, out pcaCount);
            object[] attributes = GetCustomAttributes(parameter.GetRuntimeModule(), parameter.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(parameter)); 
            if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
            return attributes;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType) 
        {
            Contract.Requires(assembly != null);
            Contract.Requires(caType != null);
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(assembly, caType, true, out pcaCount);
            int assemblyToken = RuntimeAssembly.GetToken(assembly.GetNativeHandle());
            bool isAssemblySecurityTransparent = assembly.IsAllSecurityTransparent();
            object[] attributes = GetCustomAttributes(assembly.ManifestModule as RuntimeModule, assemblyToken, pcaCount, caType, isAssemblySecurityTransparent);
            if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
            return attributes;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static Object[] GetCustomAttributes(RuntimeModule module, RuntimeType caType) 
        {
            Contract.Requires(module != null);
            Contract.Requires(caType != null);
 
            int pcaCount = 0;
            Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(module, caType, out pcaCount);
            bool isModuleSecurityTransparent = module.GetRuntimeAssembly().IsAllSecurityTransparent();
            object[] attributes = GetCustomAttributes(module, module.MetadataToken, pcaCount, caType, isModuleSecurityTransparent);
            if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
            return attributes;
        }
 
        [System.Security.SecuritySafeCritical]
        internal static bool IsAttributeDefined(RuntimeModule decoratedModule, int decoratedMetadataToken, int attributeCtorToken)
        {
            return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, null, attributeCtorToken, false);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsCustomAttributeDefined(
            RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType)
        {
            return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, attributeFilterType, 0, false);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsCustomAttributeDefined(
            RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType, int attributeCtorToken, bool mustBeInheritable)
        {
            if (decoratedModule.Assembly.ReflectionOnly)
                throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyCA"));
            Contract.EndContractBlock();
 
            CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken);
 
            if (attributeFilterType != null)
            {
                Contract.Assert(attributeCtorToken == 0);
 
                MetadataImport scope = decoratedModule.MetadataImport;
                RuntimeType attributeType;
                IRuntimeMethodInfo ctor;
                bool ctorHasParameters, isVarArg;
 
                // Optimization for the case where attributes decorate entities in the same assembly in which case 
                // we can cache the successful APTCA check between the decorated and the declared assembly.
                Assembly lastAptcaOkAssembly = null;
 
                for (int i = 0; i < car.Length; i++)
                {
                    CustomAttributeRecord caRecord = car[i];
 
                    if (FilterCustomAttributeRecord(caRecord, scope, ref lastAptcaOkAssembly,
                        decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable, null, null,
                        out attributeType, out ctor, out ctorHasParameters, out isVarArg))
                        return true;
                }
            }
            else
            {
                Contract.Assert(attributeFilterType == null);
                Contract.Assert(!MetadataToken.IsNullToken(attributeCtorToken));
 
                for (int i = 0; i < car.Length; i++)
                {
                    CustomAttributeRecord caRecord = car[i];
 
                    if (caRecord.tkCtor == attributeCtorToken)
                        return true;
                }
            }
 
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe static object[] GetCustomAttributes(
            RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType, bool isDecoratedTargetSecurityTransparent)
        {
            return GetCustomAttributes(decoratedModule, decoratedMetadataToken, pcaCount, attributeFilterType, false, null, isDecoratedTargetSecurityTransparent);
        }
 
        [System.Security.SecurityCritical]
        private unsafe static object[] GetCustomAttributes(
            RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, 
            RuntimeType attributeFilterType, bool mustBeInheritable, IList derivedAttributes, bool isDecoratedTargetSecurityTransparent)
        {
            if (decoratedModule.Assembly.ReflectionOnly)
                throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyCA"));
            Contract.EndContractBlock();
 
            MetadataImport scope = decoratedModule.MetadataImport;
            CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken);
 
            bool useObjectArray = (attributeFilterType == null || attributeFilterType.IsValueType || attributeFilterType.ContainsGenericParameters);
            Type arrayType = useObjectArray ? typeof(object) : attributeFilterType;
 
            if (attributeFilterType == null && car.Length == 0)
                return CreateAttributeArrayHelper(arrayType, 0);
 
            object[] attributes = CreateAttributeArrayHelper(arrayType, car.Length);
            int cAttributes = 0;
 
            // Custom attribute security checks are done with respect to the assembly *decorated* with the 
            // custom attribute as opposed to the *caller of GetCustomAttributes*.
            // Since this assembly might not be on the stack and the attribute ctor or property setters we're about to invoke may
            // make security demands, we push a frame on the stack as a proxy for the decorated assembly (this frame will be picked
            // up an interpreted by the security stackwalker).
            // Once we push the frame it will be automatically popped in the event of an exception, so no need to use CERs or the
            // like.
            SecurityContextFrame frame = new SecurityContextFrame();
            frame.Push(decoratedModule.GetRuntimeAssembly());
 
            // Optimization for the case where attributes decorate entities in the same assembly in which case 
            // we can cache the successful APTCA check between the decorated and the declared assembly.
            Assembly lastAptcaOkAssembly = null;
 
            for (int i = 0; i < car.Length; i++)
            {
                object attribute = null;
                CustomAttributeRecord caRecord = car[i];
 
                IRuntimeMethodInfo ctor = null;
                RuntimeType attributeType = null;
                bool ctorHasParameters, isVarArg;
                int cNamedArgs = 0;
 
                IntPtr blobStart = caRecord.blob.Signature;
                IntPtr blobEnd = (IntPtr)((byte*)blobStart + caRecord.blob.Length);
                int blobLen = (int)((byte*)blobEnd - (byte*)blobStart);
 
                if (!FilterCustomAttributeRecord(caRecord, scope, ref lastAptcaOkAssembly, 
                                                 decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable, 
                                                 attributes, derivedAttributes,
                                                 out attributeType, out ctor, out ctorHasParameters, out isVarArg))
                    continue;
 
                if (ctor != null)
                {
                    // Linktime demand checks 
                    // decoratedMetadataToken needed as it may be "transparent" in which case we do a full stack walk
                    RuntimeMethodHandle.CheckLinktimeDemands(ctor, decoratedModule, isDecoratedTargetSecurityTransparent);
                }
                else
                {
                    // 
 
 
                }
 
                // Leverage RuntimeConstructorInfo standard .ctor verfication
                RuntimeConstructorInfo.CheckCanCreateInstance(attributeType, isVarArg); 
 
                // Create custom attribute object
                if (ctorHasParameters)
                {
                    attribute = CreateCaObject(decoratedModule, ctor, ref blobStart, blobEnd, out cNamedArgs); 
                }
                else
                {
                    attribute = RuntimeTypeHandle.CreateCaInstance(attributeType, ctor);
 
                    // It is allowed by the ECMA spec to have an empty signature blob
                    if (blobLen == 0)
                        cNamedArgs = 0;
                    else
                    {
                        // Metadata is always written in little-endian format. Must account for this on
                        // big-endian platforms.
#if BIGENDIAN
                        const int CustomAttributeVersion = 0x0100;
#else
                        const int CustomAttributeVersion = 0x0001;
#endif
                        if (Marshal.ReadInt16(blobStart) != CustomAttributeVersion)
                            throw new CustomAttributeFormatException();
                        blobStart = (IntPtr)((byte*)blobStart + 2); // skip version prefix
 
                        cNamedArgs = Marshal.ReadInt16(blobStart);
                        blobStart = (IntPtr)((byte*)blobStart + 2); // skip namedArgs count
#if BIGENDIAN
                        cNamedArgs = ((cNamedArgs & 0xff00) >> 8) | ((cNamedArgs & 0x00ff) << 8);
#endif
                    }
                }
 
                for (int j = 0; j < cNamedArgs; j++)
                {
                    #region // Initialize named properties and fields
                    string name;
                    bool isProperty;
                    RuntimeType type;
                    object value;
                    
                    IntPtr blobItr = caRecord.blob.Signature;
 
                    GetPropertyOrFieldData(decoratedModule, ref blobStart, blobEnd, out name, out isProperty, out type, out value);
 
                    try
                    {
                        if (isProperty)
                        {
                            #region // Initialize property
                            if (type == null && value != null)
                            {
                                type = (RuntimeType)value.GetType();
                                if (type == Type_RuntimeType)
                                    type = Type_Type;
                            }
 
                            RuntimePropertyInfo property = null;
 
                            if (type == null)
                                property = attributeType.GetProperty(name) as RuntimePropertyInfo;
                            else
                                property = attributeType.GetProperty(name, type, Type.EmptyTypes) as RuntimePropertyInfo;
 
                            // Did we get a valid property reference?
                            if (property == null)
                            {
                                throw new CustomAttributeFormatException(
                                    String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString(
                                        isProperty ? "RFLCT.InvalidPropFail" : "RFLCT.InvalidFieldFail"), name));
                            }
 
                            RuntimeMethodInfo setMethod = property.GetSetMethod(true) as RuntimeMethodInfo;
                            
                            // Public properties may have non-public setter methods
                            if (!setMethod.IsPublic)
                                continue;
 
                            RuntimeMethodHandle.CheckLinktimeDemands(setMethod, decoratedModule, isDecoratedTargetSecurityTransparent);
 
                            setMethod.UnsafeInvoke(attribute, BindingFlags.Default, null, new object[] { value }, null);
                            #endregion
                        }
                        else
                        {
                            RtFieldInfo field = attributeType.GetField(name) as RtFieldInfo;
 
                            if (isDecoratedTargetSecurityTransparent)
                            {
                                RuntimeFieldHandle.CheckAttributeAccess(field.FieldHandle, decoratedModule.GetNativeHandle());
                            }
 
                            field.CheckConsistency(attribute);
                            field.UnsafeSetValue(attribute, value, BindingFlags.Default, Type.DefaultBinder, null);
                        }
                    }
                    catch (Exception e)
                    {
                        throw new CustomAttributeFormatException(
                            String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString(
                                isProperty ? "RFLCT.InvalidPropFail" : "RFLCT.InvalidFieldFail"), name), e);
                    }
                    #endregion
                }
 
                if (!blobStart.Equals(blobEnd))
                    throw new CustomAttributeFormatException();
 
                attributes[cAttributes++] = attribute;
            }
 
            // The frame will be popped automatically if we take an exception any time after we pushed it. So no need of a catch or
            // finally or CERs here.
            frame.Pop();
 
            if (cAttributes == car.Length && pcaCount == 0)
                return attributes;
 
            object[] result = CreateAttributeArrayHelper(arrayType, cAttributes + pcaCount);
            Array.Copy(attributes, 0, result, 0, cAttributes);
            return result;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe static bool FilterCustomAttributeRecord(
            CustomAttributeRecord caRecord,
            MetadataImport scope,
            ref Assembly lastAptcaOkAssembly, 
            RuntimeModule decoratedModule,
            MetadataToken decoratedToken,
            RuntimeType attributeFilterType,
            bool mustBeInheritable,
            object[] attributes,
            IList derivedAttributes,
            out RuntimeType attributeType,
            out IRuntimeMethodInfo ctor,
            out bool ctorHasParameters,
            out bool isVarArg)
        {
            ctor = null;
            attributeType = null;
            ctorHasParameters = false;
            isVarArg = false;
            
            IntPtr blobStart = caRecord.blob.Signature;
            IntPtr blobEnd = (IntPtr)((byte*)blobStart + caRecord.blob.Length);
 
#if FEATURE_LEGACYNETCF
            if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
                try
                {
                    // Resolve attribute type from ctor parent token found in decorated decoratedModule scope
                    attributeType = decoratedModule.ResolveType(scope.GetParentToken(caRecord.tkCtor), null, null) as RuntimeType;
                }
                catch(Exception)
                {
                    return false;
                }
            }
            else
#endif
            // Resolve attribute type from ctor parent token found in decorated decoratedModule scope
            attributeType = decoratedModule.ResolveType(scope.GetParentToken(caRecord.tkCtor), null, null) as RuntimeType;
 
 
            // Test attribute type against user provided attribute type filter
            if (!(attributeFilterType.IsAssignableFrom(attributeType)))
                return false;
 
            // Ensure if attribute type must be inheritable that it is inhertiable
            // Ensure that to consider a duplicate attribute type AllowMultiple is true
            if (!AttributeUsageCheck(attributeType, mustBeInheritable, attributes, derivedAttributes))
                return false;
 
            // Windows Runtime attributes aren't real types - they exist to be read as metadata only, and as such
            // should be filtered out of the GetCustomAttributes path.
            if ((attributeType.Attributes & TypeAttributes.WindowsRuntime) == TypeAttributes.WindowsRuntime)
            {
                return false;
            }
 
#if FEATURE_APTCA
            // APTCA checks
            RuntimeAssembly attributeAssembly = (RuntimeAssembly)attributeType.Assembly;
            RuntimeAssembly decoratedModuleAssembly = (RuntimeAssembly)decoratedModule.Assembly;
 
            if (attributeAssembly != lastAptcaOkAssembly && 
                !RuntimeAssembly.AptcaCheck(attributeAssembly, decoratedModuleAssembly))
                return false;
 
            // Cache last successful APTCA check (optimization)
            lastAptcaOkAssembly = decoratedModuleAssembly;
#endif // FEATURE_APTCA
 
            // Resolve the attribute ctor
            ConstArray ctorSig = scope.GetMethodSignature(caRecord.tkCtor);
            isVarArg = (ctorSig[0] & 0x05) != 0;
            ctorHasParameters = ctorSig[1] != 0;
 
            if (ctorHasParameters)
            {
                // Resolve method ctor token found in decorated decoratedModule scope
                ctor = ModuleHandle.ResolveMethodHandleInternal(decoratedModule.GetNativeHandle(), caRecord.tkCtor);
            }
            else
            {
                // Resolve method ctor token from decorated decoratedModule scope
                ctor = attributeType.GetTypeHandleInternal().GetDefaultConstructor();
 
                if (ctor == null && !attributeType.IsValueType)
                    throw new MissingMethodException(".ctor");
            }
 
            // Visibility checks
            MetadataToken tkParent = new MetadataToken();
                
            if (decoratedToken.IsParamDef)
            {
                tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
                tkParent = new MetadataToken(scope.GetParentToken(tkParent));
            }               
            else if (decoratedToken.IsMethodDef || decoratedToken.IsProperty || decoratedToken.IsEvent || decoratedToken.IsFieldDef) 
            {
                tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
            }
            else if (decoratedToken.IsTypeDef)
            {
                tkParent = decoratedToken;
            }
            else if (decoratedToken.IsGenericPar)
            {
                tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
 
                // decoratedToken is a generic parameter on a method. Get the declaring Type of the method.
                if (tkParent.IsMethodDef)
                    tkParent = new MetadataToken(scope.GetParentToken(tkParent));
            }
            else
            {
                // We need to relax this when we add support for other types of decorated tokens.
                Contract.Assert(decoratedToken.IsModule || decoratedToken.IsAssembly, 
                                "The decoratedToken must be either an assembly, a module, a type, or a member.");
            }
 
            // If the attribute is on a type, member, or parameter we check access against the (declaring) type,
            // otherwise we check access against the module.
            RuntimeTypeHandle parentTypeHandle = tkParent.IsTypeDef ?
                                                    decoratedModule.ModuleHandle.ResolveTypeHandle(tkParent) :
                                                    new RuntimeTypeHandle();
 
            return RuntimeMethodHandle.IsCAVisibleFromDecoratedType(attributeType.TypeHandle, ctor, parentTypeHandle, decoratedModule);
        }
        #endregion
 
        #region Private Static Methods
        [System.Security.SecurityCritical]  // auto-generated
        private static bool AttributeUsageCheck(
            RuntimeType attributeType, bool mustBeInheritable, object[] attributes, IList derivedAttributes)
        {
            AttributeUsageAttribute attributeUsageAttribute = null;
 
            if (mustBeInheritable)
            {
                attributeUsageAttribute = CustomAttribute.GetAttributeUsage(attributeType);
 
                if (!attributeUsageAttribute.Inherited)
                    return false;
            }
 
            // Legacy: AllowMultiple ignored for none inheritable attributes
 
            if (derivedAttributes == null)
                return true;
 
            for (int i = 0; i < derivedAttributes.Count; i++)
            {
                if (derivedAttributes[i].GetType() == attributeType)
                {
                    if (attributeUsageAttribute == null)
                        attributeUsageAttribute = CustomAttribute.GetAttributeUsage(attributeType);
 
                    return attributeUsageAttribute.AllowMultiple;
                }
            }
 
            return true;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static AttributeUsageAttribute GetAttributeUsage(RuntimeType decoratedAttribute)
        {
            RuntimeModule decoratedModule = decoratedAttribute.GetRuntimeModule();
            MetadataImport scope = decoratedModule.MetadataImport;
            CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedAttribute.MetadataToken);
 
            AttributeUsageAttribute attributeUsageAttribute = null;
 
            for (int i = 0; i < car.Length; i++)
            {
                CustomAttributeRecord caRecord = car[i];
                RuntimeType attributeType = decoratedModule.ResolveType(scope.GetParentToken(caRecord.tkCtor), null, null) as RuntimeType;
 
                if (attributeType != (RuntimeType)typeof(AttributeUsageAttribute))
                    continue;
 
                if (attributeUsageAttribute != null)
                    throw new FormatException(String.Format(
                        CultureInfo.CurrentUICulture, Environment.GetResourceString("Format_AttributeUsage"), attributeType));
 
                AttributeTargets targets;
                bool inherited, allowMultiple;
                ParseAttributeUsageAttribute(caRecord.blob, out targets, out inherited, out allowMultiple);
                attributeUsageAttribute = new AttributeUsageAttribute(targets, allowMultiple, inherited);
            }
 
            if (attributeUsageAttribute == null)
                return AttributeUsageAttribute.Default;
 
            return attributeUsageAttribute;
        }
        #endregion
 
        #region Private Static FCalls
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void _ParseAttributeUsageAttribute(
            IntPtr pCa, int cCa, out int targets, out bool inherited, out bool allowMultiple);
        [System.Security.SecurityCritical]  // auto-generated
        private static void ParseAttributeUsageAttribute(
            ConstArray ca, out AttributeTargets targets, out bool inherited, out bool allowMultiple)
        {
            int _targets;
            _ParseAttributeUsageAttribute(ca.Signature, ca.Length, out _targets, out inherited, out allowMultiple);
            targets = (AttributeTargets)_targets;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static unsafe extern Object _CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, byte** ppBlob, byte* pEndBlob, int* pcNamedArgs);
        [System.Security.SecurityCritical]  // auto-generated
        private static unsafe Object CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, ref IntPtr blob, IntPtr blobEnd, out int namedArgs)
        {
            byte* pBlob = (byte*)blob;
            byte* pBlobEnd = (byte*)blobEnd;
            int cNamedArgs; 
            object ca = _CreateCaObject(module, ctor, &pBlob, pBlobEnd, &cNamedArgs);
            blob = (IntPtr)pBlob;
            namedArgs = cNamedArgs;
            return ca;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private unsafe extern static void _GetPropertyOrFieldData(
            RuntimeModule pModule, byte** ppBlobStart, byte* pBlobEnd, out string name, out bool bIsProperty, out RuntimeType type, out object value);
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe static void GetPropertyOrFieldData(
            RuntimeModule module, ref IntPtr blobStart, IntPtr blobEnd, out string name, out bool isProperty, out RuntimeType type, out object value)
        {
            byte* pBlobStart = (byte*)blobStart;
            _GetPropertyOrFieldData(
                module.GetNativeHandle(), &pBlobStart, (byte*)blobEnd, out name, out isProperty, out type, out value);
            blobStart = (IntPtr)pBlobStart;
        }
 
        [System.Security.SecuritySafeCritical]
        private static object[] CreateAttributeArrayHelper(Type elementType, int elementCount)
        {
            return (object[])Array.UnsafeCreateInstance(elementType, elementCount);
        }
        #endregion
    }
 
    internal static class PseudoCustomAttribute
    {
        #region Private Static Data Members
        // Here we can avoid the need to take a lock when using Dictionary by rearranging
        // the only method that adds values to the Dictionary. For more details on 
        // Dictionary versus Hashtable thread safety:
        // See code:Dictionary#DictionaryVersusHashtableThreadSafety
        private static Dictionary<RuntimeType, RuntimeType> s_pca;
        private static int s_pcasCount;
        #endregion
 
        #region FCalls
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        unsafe private static extern void _GetSecurityAttributes(RuntimeModule module, int token, bool assembly, out object[] securityAttributes);
        [System.Security.SecurityCritical]  // auto-generated
        unsafe internal static void GetSecurityAttributes(RuntimeModule module, int token, bool assembly, out object[] securityAttributes)
        {
            _GetSecurityAttributes(module.GetNativeHandle(), token, assembly, out securityAttributes);
        }
        #endregion
 
        #region Static Constructor
        [System.Security.SecurityCritical]  // auto-generated
        static PseudoCustomAttribute()
        {
            RuntimeType[] pcas = new RuntimeType[]
            {
                // See //depot/DevDiv/private/Main/ndp/clr/src/MD/Compiler/CustAttr.cpp
                typeof(FieldOffsetAttribute) as RuntimeType, // field
#if FEATURE_SERIALIZATION
                typeof(SerializableAttribute) as RuntimeType, // class, struct, enum, delegate
#endif
                typeof(MarshalAsAttribute) as RuntimeType, // parameter, field, return-value
                typeof(ComImportAttribute) as RuntimeType, // class, interface 
#if FEATURE_SERIALIZATION
                typeof(NonSerializedAttribute) as RuntimeType, // field, inherited
#endif
                typeof(InAttribute) as RuntimeType, // parameter
                typeof(OutAttribute) as RuntimeType, // parameter
                typeof(OptionalAttribute) as RuntimeType, // parameter
                typeof(DllImportAttribute) as RuntimeType, // method
                typeof(PreserveSigAttribute) as RuntimeType, // method
                typeof(TypeForwardedToAttribute) as RuntimeType, // assembly
            };
 
            s_pcasCount = pcas.Length;
            Dictionary<RuntimeType, RuntimeType> temp_pca = new Dictionary<RuntimeType, RuntimeType>(s_pcasCount);
 
            for (int i = 0; i < s_pcasCount; i++)
            {
                VerifyPseudoCustomAttribute(pcas[i]);
                temp_pca[pcas[i]] = pcas[i];
            }
            s_pca = temp_pca;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        [Conditional("_DEBUG")]
        private static void VerifyPseudoCustomAttribute(RuntimeType pca)
        {
            // If any of these are invariants are no longer true will have to 
            // re-architect the PCA product logic and test cases -- you've been warned!
            Contract.Assert(pca.BaseType == (RuntimeType)typeof(Attribute), "Pseudo CA Error");
            AttributeUsageAttribute usage = CustomAttribute.GetAttributeUsage(pca);
            Contract.Assert(usage.Inherited == false, "Pseudo CA Error");
            //AllowMultiple is true for TypeForwardedToAttribute
            //Contract.Assert(usage.AllowMultiple == false, "Pseudo CA Error");
        }
        #endregion
 
        #region Internal Static
        internal static bool IsSecurityAttribute(RuntimeType type)
        {
#pragma warning disable 618
            return type == (RuntimeType)typeof(SecurityAttribute) || type.IsSubclassOf(typeof(SecurityAttribute));
#pragma warning restore 618
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Attribute[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool includeSecCa, out int count)
        {
            Contract.Requires(type != null);
            Contract.Requires(caType != null);
 
            count = 0;
 
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
                return new Attribute[0];
 
            List<Attribute> pcas = new List<Attribute>();
            Attribute pca = null;
 
#if FEATURE_SERIALIZATION
            if (all || caType == (RuntimeType)typeof(SerializableAttribute))
            {
                pca = SerializableAttribute.GetCustomAttribute(type);
                if (pca != null) pcas.Add(pca);
            }
#endif 
            if (all || caType == (RuntimeType)typeof(ComImportAttribute))
            {
                pca = ComImportAttribute.GetCustomAttribute(type);
                if (pca != null) pcas.Add(pca);
            }
            if (includeSecCa && (all || IsSecurityAttribute(caType)))
            {
                if (!type.IsGenericParameter && type.GetElementType() == null)
                {
                    if (type.IsGenericType)
                        type = (RuntimeType)type.GetGenericTypeDefinition();
 
                    object[] securityAttributes;
                    GetSecurityAttributes(type.Module.ModuleHandle.GetRuntimeModule(), type.MetadataToken, false, out securityAttributes);
                    if (securityAttributes != null)
                        foreach (object a in securityAttributes)
                            if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
                                pcas.Add((Attribute)a);
                }
            }
 
            count = pcas.Count;
            return pcas.ToArray();
        }
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeType type, RuntimeType caType)
        {
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
                return false;
 
#if FEATURE_SERIALIZATION
            if (all || caType == (RuntimeType)typeof(SerializableAttribute)) 
            { 
                if (SerializableAttribute.IsDefined(type)) return true;
            }
#endif
            if (all || caType == (RuntimeType)typeof(ComImportAttribute)) 
            { 
                if (ComImportAttribute.IsDefined(type)) return true;
            }
            if (all || IsSecurityAttribute(caType))
            {
                int count;
                if (GetCustomAttributes(type, caType, true, out count).Length != 0)
                    return true;
            }
 
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Attribute[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool includeSecCa, out int count)
        {
            Contract.Requires(method != null);
            Contract.Requires(caType != null);
 
            count = 0;
 
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
                return new Attribute[0];
 
            List<Attribute> pcas = new List<Attribute>();
            Attribute pca = null;
 
            if (all || caType == (RuntimeType)typeof(DllImportAttribute))
            {
                pca = DllImportAttribute.GetCustomAttribute(method);
                if (pca != null) pcas.Add(pca);
            }
            if (all || caType == (RuntimeType)typeof(PreserveSigAttribute))
            {
                pca = PreserveSigAttribute.GetCustomAttribute(method);
                if (pca != null) pcas.Add(pca);
            }
            if (includeSecCa && (all || IsSecurityAttribute(caType)))
            {
                object[] securityAttributes;
 
                GetSecurityAttributes(method.Module.ModuleHandle.GetRuntimeModule(), method.MetadataToken, false, out securityAttributes);
                if (securityAttributes != null)
                    foreach (object a in securityAttributes)
                        if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
                            pcas.Add((Attribute)a);
            }
 
            count = pcas.Count;
            return pcas.ToArray();
        }
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType)
        {
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null)
                return false;
 
            if (all || caType == (RuntimeType)typeof(DllImportAttribute))
            {
                if (DllImportAttribute.IsDefined(method)) return true;
            }
            if (all || caType == (RuntimeType)typeof(PreserveSigAttribute))
            {
                if (PreserveSigAttribute.IsDefined(method)) return true;
            }
            if (all || IsSecurityAttribute(caType))
            {
                int count;
 
                if (GetCustomAttributes(method, caType, true, out count).Length != 0)
                    return true;
            }
 
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Attribute[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, out int count)
        {
            Contract.Requires(parameter != null);
            Contract.Requires(caType != null);
 
            count = 0;
 
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null)
                return null;
 
            Attribute[] pcas = new Attribute[s_pcasCount];
            Attribute pca = null;
 
            if (all || caType == (RuntimeType)typeof(InAttribute))
            {
                pca = InAttribute.GetCustomAttribute(parameter);
                if (pca != null) pcas[count++] = pca;
            }
            if (all || caType == (RuntimeType)typeof(OutAttribute))
            {
                pca = OutAttribute.GetCustomAttribute(parameter);
                if (pca != null) pcas[count++] = pca;
            }
            if (all || caType == (RuntimeType)typeof(OptionalAttribute))
            {
                pca = OptionalAttribute.GetCustomAttribute(parameter);
                if (pca != null) pcas[count++] = pca;
            }
            if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
            {
                pca = MarshalAsAttribute.GetCustomAttribute(parameter);
                if (pca != null) pcas[count++] = pca;
            }
            return pcas;
        }
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType)
        {
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null)
                return false;
 
 
            if (all || caType == (RuntimeType)typeof(InAttribute))
            {
                if (InAttribute.IsDefined(parameter)) return true;
            }
            if (all || caType == (RuntimeType)typeof(OutAttribute))
            {
                if (OutAttribute.IsDefined(parameter)) return true;
            }
            if (all || caType == (RuntimeType)typeof(OptionalAttribute))
            {
                if (OptionalAttribute.IsDefined(parameter)) return true;
            }
            if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
            {
                if (MarshalAsAttribute.IsDefined(parameter)) return true;
            }
 
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Attribute[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType, bool includeSecCa, out int count)
        {
            count = 0;
 
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
 
            if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
                return new Attribute[0];
 
            List<Attribute> pcas = new List<Attribute>();
            if (includeSecCa && (all || IsSecurityAttribute(caType)))
            {
                object[] securityAttributes;
 
                GetSecurityAttributes(assembly.ManifestModule.ModuleHandle.GetRuntimeModule(), RuntimeAssembly.GetToken(assembly.GetNativeHandle()), true, out securityAttributes);
                if (securityAttributes != null)
                    foreach (object a in securityAttributes)
                        if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
                            pcas.Add((Attribute)a);
            }
 
            //TypeForwardedToAttribute.GetCustomAttribute(assembly) throws FileNotFoundException if the forwarded-to
            //assemblies are not present. This breaks many V4 scenarios because some framework types are forwarded 
            //to assemblies not included in the client SKU. Let's omit TypeForwardedTo for now until we have a better solution.
 
            //if (all || caType == (RuntimeType)typeof(TypeForwardedToAttribute))
            //{
            //    TypeForwardedToAttribute[] attrs = TypeForwardedToAttribute.GetCustomAttribute(assembly);
            //    pcas.AddRange(attrs);
            //}
 
            count = pcas.Count;
            return pcas.ToArray();
        }
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType)
        {
            int count;
            return GetCustomAttributes(assembly, caType, true, out count).Length > 0;
        }
 
        internal static Attribute[] GetCustomAttributes(RuntimeModule module, RuntimeType caType, out int count)
        {
            count = 0;
            return null;
        }
        internal static bool IsDefined(RuntimeModule module, RuntimeType caType)
        {
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Attribute[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, out int count)
        {
            Contract.Requires(field != null);
            Contract.Requires(caType != null);
 
            count = 0;
 
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null)
                return null;
 
            Attribute[] pcas = new Attribute[s_pcasCount];
            Attribute pca = null;
 
            if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
            {
                pca = MarshalAsAttribute.GetCustomAttribute(field);
                if (pca != null) pcas[count++] = pca;
            }
            if (all || caType == (RuntimeType)typeof(FieldOffsetAttribute))
            {
                pca = FieldOffsetAttribute.GetCustomAttribute(field);
                if (pca != null) pcas[count++] = pca;
            }
#if FEATURE_SERIALIZATION
            if (all || caType == (RuntimeType)typeof(NonSerializedAttribute))
            {
                pca = NonSerializedAttribute.GetCustomAttribute(field);
                if (pca != null) pcas[count++] = pca;
            }
#endif
            return pcas;
        }
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType)
        {
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
            if (!all && s_pca.GetValueOrDefault(caType) == null)
                return false;
 
            if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
            {
                if (MarshalAsAttribute.IsDefined(field)) return true;
            }
            if (all || caType == (RuntimeType)typeof(FieldOffsetAttribute))
            {
                if (FieldOffsetAttribute.IsDefined(field)) return true;
            }
#if FEATURE_SERIALIZATION
            if (all || caType == (RuntimeType)typeof(NonSerializedAttribute)) 
            { 
                if (NonSerializedAttribute.IsDefined(field)) return true;
            }
#endif
 
            return false;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static Attribute[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType, bool includeSecCa, out int count)
        {
            count = 0;
 
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
 
            if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
                return new Attribute[0];
 
            List<Attribute> pcas = new List<Attribute>();
 
            if (includeSecCa && (all || IsSecurityAttribute(caType)))
            {
                object[] securityAttributes;
 
                GetSecurityAttributes(ctor.Module.ModuleHandle.GetRuntimeModule(), ctor.MetadataToken, false, out securityAttributes);
                if (securityAttributes != null)
                    foreach (object a in securityAttributes)
                        if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
                            pcas.Add((Attribute)a);
            }
 
            count = pcas.Count;
            return pcas.ToArray();
        }
        [System.Security.SecurityCritical]  // auto-generated
        internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType)
        {
            bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
 
            if (!all && s_pca.GetValueOrDefault(caType) == null)
                return false;
 
            if (all || IsSecurityAttribute(caType))
            {
                int count;
 
                if (GetCustomAttributes(ctor, caType, true, out count).Length != 0)
                    return true;
            }
 
            return false;
        }
 
        internal static Attribute[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType, out int count)
        {
            count = 0;
            return null;
        }
        internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType)
        {
            return false;
        }
 
        internal static Attribute[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType, out int count)
        {
            count = 0;
            return null;
        }
        internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType)
        {
            return false;
        }
        #endregion
    }
}