1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
8 using System.Runtime.CompilerServices;
9 using System.Runtime.InteropServices;
10 using System.Collections;
11 using System.Collections.Generic;
12 using System.Resources;
13 using System.Diagnostics;
14 using System.Diagnostics.Tracing;
15 using System.Globalization;
16 using System.Security;
17 using System.Runtime.ConstrainedExecution;
18 using System.Runtime.Versioning;
20 namespace System.Reflection
22 public class CustomAttributeData
24 #region Public Static Members
25 public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo target)
28 throw new ArgumentNullException(nameof(target));
30 return target.GetCustomAttributesData();
33 public static IList<CustomAttributeData> GetCustomAttributes(Module target)
36 throw new ArgumentNullException(nameof(target));
38 return target.GetCustomAttributesData();
41 public static IList<CustomAttributeData> GetCustomAttributes(Assembly target)
44 throw new ArgumentNullException(nameof(target));
46 return target.GetCustomAttributesData();
49 public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo target)
52 throw new ArgumentNullException(nameof(target));
54 return target.GetCustomAttributesData();
58 #region Internal Static Members
59 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeType target)
61 Debug.Assert(target != null);
63 IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
66 Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeType)target, typeof(object) as RuntimeType, out pcaCount);
71 CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
72 cad.CopyTo(pca, pcaCount);
73 for (int i = 0; i < pcaCount; i++)
75 pca[i] = new CustomAttributeData(a[i]);
78 return Array.AsReadOnly(pca);
81 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeFieldInfo target)
83 Debug.Assert(target != null);
85 IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
88 Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeFieldInfo)target, typeof(object) as RuntimeType, out pcaCount);
93 CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
94 cad.CopyTo(pca, pcaCount);
95 for (int i = 0; i < pcaCount; i++)
97 pca[i] = new CustomAttributeData(a[i]);
100 return Array.AsReadOnly(pca);
103 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeMethodInfo target)
105 Debug.Assert(target != null);
107 IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
110 Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeMethodInfo)target, typeof(object) as RuntimeType, out pcaCount);
115 CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
116 cad.CopyTo(pca, pcaCount);
117 for (int i = 0; i < pcaCount; i++)
119 pca[i] = new CustomAttributeData(a[i]);
122 return Array.AsReadOnly(pca);
125 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeConstructorInfo target)
127 Debug.Assert(target != null);
129 return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
132 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeEventInfo target)
134 Debug.Assert(target != null);
136 return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
139 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimePropertyInfo target)
141 Debug.Assert(target != null);
143 return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
146 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeModule target)
148 Debug.Assert(target != null);
150 if (target.IsResource())
151 return new List<CustomAttributeData>();
153 return GetCustomAttributes(target, target.MetadataToken);
156 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeAssembly target)
158 Debug.Assert(target != null);
160 IList<CustomAttributeData> cad = GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target.GetNativeHandle()));
163 Attribute[] a = PseudoCustomAttribute.GetCustomAttributes(target, typeof(object) as RuntimeType, out pcaCount);
168 CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
169 cad.CopyTo(pca, pcaCount);
170 for (int i = 0; i < pcaCount; i++)
172 pca[i] = new CustomAttributeData(a[i]);
175 return Array.AsReadOnly(pca);
178 internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeParameterInfo target)
180 Debug.Assert(target != null);
182 IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
185 Attribute[] a = PseudoCustomAttribute.GetCustomAttributes(target, typeof(object) as RuntimeType, out pcaCount);
190 CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
191 cad.CopyTo(pca, pcaCount);
192 for (int i = 0; i < pcaCount; i++)
193 pca[i] = new CustomAttributeData(a[i]);
195 return Array.AsReadOnly(pca);
199 #region Private Static Methods
200 private static CustomAttributeEncoding TypeToCustomAttributeEncoding(RuntimeType type)
202 if (type == (RuntimeType)typeof(int))
203 return CustomAttributeEncoding.Int32;
206 return CustomAttributeEncoding.Enum;
208 if (type == (RuntimeType)typeof(string))
209 return CustomAttributeEncoding.String;
211 if (type == (RuntimeType)typeof(Type))
212 return CustomAttributeEncoding.Type;
214 if (type == (RuntimeType)typeof(object))
215 return CustomAttributeEncoding.Object;
218 return CustomAttributeEncoding.Array;
220 if (type == (RuntimeType)typeof(char))
221 return CustomAttributeEncoding.Char;
223 if (type == (RuntimeType)typeof(bool))
224 return CustomAttributeEncoding.Boolean;
226 if (type == (RuntimeType)typeof(byte))
227 return CustomAttributeEncoding.Byte;
229 if (type == (RuntimeType)typeof(sbyte))
230 return CustomAttributeEncoding.SByte;
232 if (type == (RuntimeType)typeof(short))
233 return CustomAttributeEncoding.Int16;
235 if (type == (RuntimeType)typeof(ushort))
236 return CustomAttributeEncoding.UInt16;
238 if (type == (RuntimeType)typeof(uint))
239 return CustomAttributeEncoding.UInt32;
241 if (type == (RuntimeType)typeof(long))
242 return CustomAttributeEncoding.Int64;
244 if (type == (RuntimeType)typeof(ulong))
245 return CustomAttributeEncoding.UInt64;
247 if (type == (RuntimeType)typeof(float))
248 return CustomAttributeEncoding.Float;
250 if (type == (RuntimeType)typeof(double))
251 return CustomAttributeEncoding.Double;
253 // System.Enum is neither an Enum nor a Class
254 if (type == (RuntimeType)typeof(Enum))
255 return CustomAttributeEncoding.Object;
258 return CustomAttributeEncoding.Object;
260 if (type.IsInterface)
261 return CustomAttributeEncoding.Object;
263 if (type.IsValueType)
264 return CustomAttributeEncoding.Undefined;
266 throw new ArgumentException(SR.Argument_InvalidKindOfTypeForCA, nameof(type));
268 private static CustomAttributeType InitCustomAttributeType(RuntimeType parameterType)
270 CustomAttributeEncoding encodedType = CustomAttributeData.TypeToCustomAttributeEncoding(parameterType);
271 CustomAttributeEncoding encodedArrayType = CustomAttributeEncoding.Undefined;
272 CustomAttributeEncoding encodedEnumType = CustomAttributeEncoding.Undefined;
273 string enumName = null;
275 if (encodedType == CustomAttributeEncoding.Array)
277 parameterType = (RuntimeType)parameterType.GetElementType();
278 encodedArrayType = CustomAttributeData.TypeToCustomAttributeEncoding(parameterType);
281 if (encodedType == CustomAttributeEncoding.Enum || encodedArrayType == CustomAttributeEncoding.Enum)
283 encodedEnumType = TypeToCustomAttributeEncoding((RuntimeType)Enum.GetUnderlyingType(parameterType));
284 enumName = parameterType.AssemblyQualifiedName;
287 return new CustomAttributeType(encodedType, encodedArrayType, encodedEnumType, enumName);
289 private static IList<CustomAttributeData> GetCustomAttributes(RuntimeModule module, int tkTarget)
291 CustomAttributeRecord[] records = GetCustomAttributeRecords(module, tkTarget);
293 CustomAttributeData[] customAttributes = new CustomAttributeData[records.Length];
294 for (int i = 0; i < records.Length; i++)
295 customAttributes[i] = new CustomAttributeData(module, records[i]);
297 return Array.AsReadOnly(customAttributes);
301 #region Internal Static Members
302 internal unsafe static CustomAttributeRecord[] GetCustomAttributeRecords(RuntimeModule module, int targetToken)
304 MetadataImport scope = module.MetadataImport;
306 MetadataEnumResult tkCustomAttributeTokens;
307 scope.EnumCustomAttributes(targetToken, out tkCustomAttributeTokens);
309 if (tkCustomAttributeTokens.Length == 0)
311 return Array.Empty<CustomAttributeRecord>();
314 CustomAttributeRecord[] records = new CustomAttributeRecord[tkCustomAttributeTokens.Length];
316 for (int i = 0; i < records.Length; i++)
318 scope.GetCustomAttributeProps(
319 tkCustomAttributeTokens[i], out records[i].tkCtor.Value, out records[i].blob);
325 internal static CustomAttributeTypedArgument Filter(IList<CustomAttributeData> attrs, Type caType, int parameter)
327 for (int i = 0; i < attrs.Count; i++)
329 if (attrs[i].Constructor.DeclaringType == caType)
331 return attrs[i].ConstructorArguments[parameter];
335 return new CustomAttributeTypedArgument();
339 #region Private Data Members
340 private ConstructorInfo m_ctor;
341 private RuntimeModule m_scope;
342 private MemberInfo[] m_members;
343 private CustomAttributeCtorParameter[] m_ctorParams;
344 private CustomAttributeNamedParameter[] m_namedParams;
345 private IList<CustomAttributeTypedArgument> m_typedCtorArgs;
346 private IList<CustomAttributeNamedArgument> m_namedArgs;
350 protected CustomAttributeData()
354 private CustomAttributeData(RuntimeModule scope, CustomAttributeRecord caRecord)
357 m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(scope, caRecord.tkCtor);
359 ParameterInfo[] parameters = m_ctor.GetParametersNoCopy();
360 m_ctorParams = new CustomAttributeCtorParameter[parameters.Length];
361 for (int i = 0; i < parameters.Length; i++)
362 m_ctorParams[i] = new CustomAttributeCtorParameter(InitCustomAttributeType((RuntimeType)parameters[i].ParameterType));
364 FieldInfo[] fields = m_ctor.DeclaringType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
365 PropertyInfo[] properties = m_ctor.DeclaringType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
366 m_namedParams = new CustomAttributeNamedParameter[properties.Length + fields.Length];
367 for (int i = 0; i < fields.Length; i++)
368 m_namedParams[i] = new CustomAttributeNamedParameter(
369 fields[i].Name, CustomAttributeEncoding.Field, InitCustomAttributeType((RuntimeType)fields[i].FieldType));
370 for (int i = 0; i < properties.Length; i++)
371 m_namedParams[i + fields.Length] = new CustomAttributeNamedParameter(
372 properties[i].Name, CustomAttributeEncoding.Property, InitCustomAttributeType((RuntimeType)properties[i].PropertyType));
374 m_members = new MemberInfo[fields.Length + properties.Length];
375 fields.CopyTo(m_members, 0);
376 properties.CopyTo(m_members, fields.Length);
378 CustomAttributeEncodedArgument.ParseAttributeArguments(caRecord.blob, ref m_ctorParams, ref m_namedParams, m_scope);
382 #region Pseudo Custom Attribute Constructor
383 internal CustomAttributeData(Attribute attribute)
385 if (attribute is DllImportAttribute)
386 Init((DllImportAttribute)attribute);
387 else if (attribute is FieldOffsetAttribute)
388 Init((FieldOffsetAttribute)attribute);
389 else if (attribute is MarshalAsAttribute)
390 Init((MarshalAsAttribute)attribute);
391 else if (attribute is TypeForwardedToAttribute)
392 Init((TypeForwardedToAttribute)attribute);
396 private void Init(DllImportAttribute dllImport)
398 Type type = typeof(DllImportAttribute);
399 m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
400 m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[]
402 new CustomAttributeTypedArgument(dllImport.Value),
405 m_namedArgs = Array.AsReadOnly(new CustomAttributeNamedArgument[]
407 new CustomAttributeNamedArgument(type.GetField("EntryPoint"), dllImport.EntryPoint),
408 new CustomAttributeNamedArgument(type.GetField("CharSet"), dllImport.CharSet),
409 new CustomAttributeNamedArgument(type.GetField("ExactSpelling"), dllImport.ExactSpelling),
410 new CustomAttributeNamedArgument(type.GetField("SetLastError"), dllImport.SetLastError),
411 new CustomAttributeNamedArgument(type.GetField("PreserveSig"), dllImport.PreserveSig),
412 new CustomAttributeNamedArgument(type.GetField("CallingConvention"), dllImport.CallingConvention),
413 new CustomAttributeNamedArgument(type.GetField("BestFitMapping"), dllImport.BestFitMapping),
414 new CustomAttributeNamedArgument(type.GetField("ThrowOnUnmappableChar"), dllImport.ThrowOnUnmappableChar)
417 private void Init(FieldOffsetAttribute fieldOffset)
419 m_ctor = typeof(FieldOffsetAttribute).GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
420 m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[] {
421 new CustomAttributeTypedArgument(fieldOffset.Value)
423 m_namedArgs = Array.AsReadOnly(Array.Empty<CustomAttributeNamedArgument>());
425 private void Init(MarshalAsAttribute marshalAs)
427 Type type = typeof(MarshalAsAttribute);
428 m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
429 m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[]
431 new CustomAttributeTypedArgument(marshalAs.Value),
434 int i = 3; // ArraySubType, SizeParamIndex, SizeConst
435 if (marshalAs.MarshalType != null) i++;
436 if (marshalAs.MarshalTypeRef != null) i++;
437 if (marshalAs.MarshalCookie != null) i++;
438 i++; // IidParameterIndex
439 i++; // SafeArraySubType
440 if (marshalAs.SafeArrayUserDefinedSubType != null) i++;
441 CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[i];
443 // For compatibility with previous runtimes, we always include the following 5 attributes, regardless
444 // of if they apply to the UnmanagedType being marshaled or not.
446 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("ArraySubType"), marshalAs.ArraySubType);
447 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SizeParamIndex"), marshalAs.SizeParamIndex);
448 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SizeConst"), marshalAs.SizeConst);
449 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("IidParameterIndex"), marshalAs.IidParameterIndex);
450 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArraySubType"), marshalAs.SafeArraySubType);
451 if (marshalAs.MarshalType != null)
452 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalType"), marshalAs.MarshalType);
453 if (marshalAs.MarshalTypeRef != null)
454 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalTypeRef"), marshalAs.MarshalTypeRef);
455 if (marshalAs.MarshalCookie != null)
456 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalCookie"), marshalAs.MarshalCookie);
457 if (marshalAs.SafeArrayUserDefinedSubType != null)
458 namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArrayUserDefinedSubType"), marshalAs.SafeArrayUserDefinedSubType);
460 m_namedArgs = Array.AsReadOnly(namedArgs);
462 private void Init(TypeForwardedToAttribute forwardedTo)
464 Type type = typeof(TypeForwardedToAttribute);
466 Type[] sig = new Type[] { typeof(Type) };
467 m_ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, sig, null);
469 CustomAttributeTypedArgument[] typedArgs = new CustomAttributeTypedArgument[1];
470 typedArgs[0] = new CustomAttributeTypedArgument(typeof(Type), forwardedTo.Destination);
471 m_typedCtorArgs = Array.AsReadOnly(typedArgs);
473 CustomAttributeNamedArgument[] namedArgs = Array.Empty<CustomAttributeNamedArgument>();
474 m_namedArgs = Array.AsReadOnly(namedArgs);
476 private void Init(object pca)
478 m_ctor = pca.GetType().GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
479 m_typedCtorArgs = Array.AsReadOnly(Array.Empty<CustomAttributeTypedArgument>());
480 m_namedArgs = Array.AsReadOnly(Array.Empty<CustomAttributeNamedArgument>());
484 #region Object Override
485 public override string ToString()
487 string ctorArgs = "";
488 for (int i = 0; i < ConstructorArguments.Count; i++)
489 ctorArgs += String.Format(CultureInfo.CurrentCulture, i == 0 ? "{0}" : ", {0}", ConstructorArguments[i]);
491 string namedArgs = "";
492 for (int i = 0; i < NamedArguments.Count; i++)
493 namedArgs += String.Format(CultureInfo.CurrentCulture, i == 0 && ctorArgs.Length == 0 ? "{0}" : ", {0}", NamedArguments[i]);
495 return String.Format(CultureInfo.CurrentCulture, "[{0}({1}{2})]", Constructor.DeclaringType.FullName, ctorArgs, namedArgs);
497 public override int GetHashCode()
499 return base.GetHashCode();
501 public override bool Equals(object obj)
503 return obj == (object)this;
507 #region Public Members
508 public Type AttributeType { get { return Constructor.DeclaringType; } }
510 public virtual ConstructorInfo Constructor { get { return m_ctor; } }
512 public virtual IList<CustomAttributeTypedArgument> ConstructorArguments
516 if (m_typedCtorArgs == null)
518 CustomAttributeTypedArgument[] typedCtorArgs = new CustomAttributeTypedArgument[m_ctorParams.Length];
520 for (int i = 0; i < typedCtorArgs.Length; i++)
522 CustomAttributeEncodedArgument encodedArg = m_ctorParams[i].CustomAttributeEncodedArgument;
524 typedCtorArgs[i] = new CustomAttributeTypedArgument(m_scope, m_ctorParams[i].CustomAttributeEncodedArgument);
527 m_typedCtorArgs = Array.AsReadOnly(typedCtorArgs);
530 return m_typedCtorArgs;
534 public virtual IList<CustomAttributeNamedArgument> NamedArguments
538 if (m_namedArgs == null)
540 if (m_namedParams == null)
544 for (int i = 0; i < m_namedParams.Length; i++)
546 if (m_namedParams[i].EncodedArgument.CustomAttributeType.EncodedType != CustomAttributeEncoding.Undefined)
550 CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[cNamedArgs];
552 for (int i = 0, j = 0; i < m_namedParams.Length; i++)
554 if (m_namedParams[i].EncodedArgument.CustomAttributeType.EncodedType != CustomAttributeEncoding.Undefined)
555 namedArgs[j++] = new CustomAttributeNamedArgument(
556 m_members[i], new CustomAttributeTypedArgument(m_scope, m_namedParams[i].EncodedArgument));
559 m_namedArgs = Array.AsReadOnly(namedArgs);
568 public struct CustomAttributeNamedArgument
570 #region Public Static Members
571 public static bool operator ==(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right)
573 return left.Equals(right);
575 public static bool operator !=(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right)
577 return !left.Equals(right);
581 #region Private Data Members
582 private MemberInfo m_memberInfo;
583 private CustomAttributeTypedArgument m_value;
587 public CustomAttributeNamedArgument(MemberInfo memberInfo, object value)
589 if (memberInfo == null)
590 throw new ArgumentNullException(nameof(memberInfo));
593 FieldInfo field = memberInfo as FieldInfo;
594 PropertyInfo property = memberInfo as PropertyInfo;
597 type = field.FieldType;
598 else if (property != null)
599 type = property.PropertyType;
601 throw new ArgumentException(SR.Argument_InvalidMemberForNamedArgument);
603 m_memberInfo = memberInfo;
604 m_value = new CustomAttributeTypedArgument(type, value);
607 public CustomAttributeNamedArgument(MemberInfo memberInfo, CustomAttributeTypedArgument typedArgument)
609 if (memberInfo == null)
610 throw new ArgumentNullException(nameof(memberInfo));
612 m_memberInfo = memberInfo;
613 m_value = typedArgument;
617 #region Object Override
618 public override string ToString()
620 if (m_memberInfo == null)
621 return base.ToString();
623 return String.Format(CultureInfo.CurrentCulture, "{0} = {1}", MemberInfo.Name, TypedValue.ToString(ArgumentType != typeof(object)));
625 public override int GetHashCode()
627 return base.GetHashCode();
629 public override bool Equals(object obj)
631 return obj == (object)this;
635 #region Internal Members
636 internal Type ArgumentType
640 return m_memberInfo is FieldInfo ?
641 ((FieldInfo)m_memberInfo).FieldType :
642 ((PropertyInfo)m_memberInfo).PropertyType;
647 #region Public Members
648 public MemberInfo MemberInfo { get { return m_memberInfo; } }
649 public CustomAttributeTypedArgument TypedValue { get { return m_value; } }
650 public string MemberName { get { return MemberInfo.Name; } }
651 public bool IsField { get { return MemberInfo is FieldInfo; } }
656 public struct CustomAttributeTypedArgument
658 #region Public Static Members
659 public static bool operator ==(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right)
661 return left.Equals(right);
663 public static bool operator !=(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right)
665 return !left.Equals(right);
669 #region Private Static Methods
670 private static Type CustomAttributeEncodingToType(CustomAttributeEncoding encodedType)
674 case (CustomAttributeEncoding.Enum):
677 case (CustomAttributeEncoding.Int32):
680 case (CustomAttributeEncoding.String):
681 return typeof(string);
683 case (CustomAttributeEncoding.Type):
686 case (CustomAttributeEncoding.Array):
687 return typeof(Array);
689 case (CustomAttributeEncoding.Char):
692 case (CustomAttributeEncoding.Boolean):
695 case (CustomAttributeEncoding.SByte):
696 return typeof(sbyte);
698 case (CustomAttributeEncoding.Byte):
701 case (CustomAttributeEncoding.Int16):
702 return typeof(short);
704 case (CustomAttributeEncoding.UInt16):
705 return typeof(ushort);
707 case (CustomAttributeEncoding.UInt32):
710 case (CustomAttributeEncoding.Int64):
713 case (CustomAttributeEncoding.UInt64):
714 return typeof(ulong);
716 case (CustomAttributeEncoding.Float):
717 return typeof(float);
719 case (CustomAttributeEncoding.Double):
720 return typeof(double);
722 case (CustomAttributeEncoding.Object):
723 return typeof(object);
726 throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)encodedType), nameof(encodedType));
730 private static object EncodedValueToRawValue(long val, CustomAttributeEncoding encodedType)
734 case CustomAttributeEncoding.Boolean:
735 return (byte)val != 0;
737 case CustomAttributeEncoding.Char:
740 case CustomAttributeEncoding.Byte:
743 case CustomAttributeEncoding.SByte:
746 case CustomAttributeEncoding.Int16:
749 case CustomAttributeEncoding.UInt16:
752 case CustomAttributeEncoding.Int32:
755 case CustomAttributeEncoding.UInt32:
758 case CustomAttributeEncoding.Int64:
761 case CustomAttributeEncoding.UInt64:
764 case CustomAttributeEncoding.Float:
765 unsafe { return *(float*)&val; }
767 case CustomAttributeEncoding.Double:
768 unsafe { return *(double*)&val; }
771 throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)val), nameof(val));
774 private static RuntimeType ResolveType(RuntimeModule scope, string typeName)
776 RuntimeType type = RuntimeTypeHandle.GetTypeByNameUsingCARules(typeName, scope);
779 throw new InvalidOperationException(
780 String.Format(CultureInfo.CurrentUICulture, SR.Arg_CATypeResolutionFailed, typeName));
786 #region Private Data Members
787 private object m_value;
788 private Type m_argumentType;
792 public CustomAttributeTypedArgument(Type argumentType, object value)
794 // value can be null.
795 if (argumentType == null)
796 throw new ArgumentNullException(nameof(argumentType));
798 m_value = (value == null) ? null : CanonicalizeValue(value);
799 m_argumentType = argumentType;
802 public CustomAttributeTypedArgument(object value)
804 // value cannot be null.
806 throw new ArgumentNullException(nameof(value));
808 m_value = CanonicalizeValue(value);
809 m_argumentType = value.GetType();
812 private static object CanonicalizeValue(object value)
814 Debug.Assert(value != null);
816 if (value.GetType().IsEnum)
818 return ((Enum)value).GetValue();
823 internal CustomAttributeTypedArgument(RuntimeModule scope, CustomAttributeEncodedArgument encodedArg)
825 CustomAttributeEncoding encodedType = encodedArg.CustomAttributeType.EncodedType;
827 if (encodedType == CustomAttributeEncoding.Undefined)
828 throw new ArgumentException(null, nameof(encodedArg));
830 else if (encodedType == CustomAttributeEncoding.Enum)
832 m_argumentType = ResolveType(scope, encodedArg.CustomAttributeType.EnumName);
833 m_value = EncodedValueToRawValue(encodedArg.PrimitiveValue, encodedArg.CustomAttributeType.EncodedEnumType);
835 else if (encodedType == CustomAttributeEncoding.String)
837 m_argumentType = typeof(string);
838 m_value = encodedArg.StringValue;
840 else if (encodedType == CustomAttributeEncoding.Type)
842 m_argumentType = typeof(Type);
846 if (encodedArg.StringValue != null)
847 m_value = ResolveType(scope, encodedArg.StringValue);
849 else if (encodedType == CustomAttributeEncoding.Array)
851 encodedType = encodedArg.CustomAttributeType.EncodedArrayType;
854 if (encodedType == CustomAttributeEncoding.Enum)
856 elementType = ResolveType(scope, encodedArg.CustomAttributeType.EnumName);
860 elementType = CustomAttributeEncodingToType(encodedType);
863 m_argumentType = elementType.MakeArrayType();
865 if (encodedArg.ArrayValue == null)
871 CustomAttributeTypedArgument[] arrayValue = new CustomAttributeTypedArgument[encodedArg.ArrayValue.Length];
872 for (int i = 0; i < arrayValue.Length; i++)
873 arrayValue[i] = new CustomAttributeTypedArgument(scope, encodedArg.ArrayValue[i]);
875 m_value = Array.AsReadOnly(arrayValue);
880 m_argumentType = CustomAttributeEncodingToType(encodedType);
881 m_value = EncodedValueToRawValue(encodedArg.PrimitiveValue, encodedType);
886 #region Object Overrides
887 public override string ToString() { return ToString(false); }
889 internal string ToString(bool typed)
891 if (m_argumentType == null)
892 return base.ToString();
894 if (ArgumentType.IsEnum)
895 return String.Format(CultureInfo.CurrentCulture, typed ? "{0}" : "({1}){0}", Value, ArgumentType.FullName);
897 else if (Value == null)
898 return String.Format(CultureInfo.CurrentCulture, typed ? "null" : "({0})null", ArgumentType.Name);
900 else if (ArgumentType == typeof(string))
901 return String.Format(CultureInfo.CurrentCulture, "\"{0}\"", Value);
903 else if (ArgumentType == typeof(char))
904 return String.Format(CultureInfo.CurrentCulture, "'{0}'", Value);
906 else if (ArgumentType == typeof(Type))
907 return String.Format(CultureInfo.CurrentCulture, "typeof({0})", ((Type)Value).FullName);
909 else if (ArgumentType.IsArray)
911 string result = null;
912 IList<CustomAttributeTypedArgument> array = Value as IList<CustomAttributeTypedArgument>;
914 Type elementType = ArgumentType.GetElementType();
915 result = String.Format(CultureInfo.CurrentCulture, @"new {0}[{1}] {{ ", elementType.IsEnum ? elementType.FullName : elementType.Name, array.Count);
917 for (int i = 0; i < array.Count; i++)
918 result += String.Format(CultureInfo.CurrentCulture, i == 0 ? "{0}" : ", {0}", array[i].ToString(elementType != typeof(object)));
920 return result += " }";
923 return String.Format(CultureInfo.CurrentCulture, typed ? "{0}" : "({1}){0}", Value, ArgumentType.Name);
926 public override int GetHashCode()
928 return base.GetHashCode();
930 public override bool Equals(object obj)
932 return obj == (object)this;
936 #region Public Members
937 public Type ArgumentType
941 return m_argumentType;
954 internal struct CustomAttributeRecord
956 internal ConstArray blob;
957 internal MetadataToken tkCtor;
960 internal enum CustomAttributeEncoding : int
963 Boolean = CorElementType.Boolean,
964 Char = CorElementType.Char,
965 SByte = CorElementType.I1,
966 Byte = CorElementType.U1,
967 Int16 = CorElementType.I2,
968 UInt16 = CorElementType.U2,
969 Int32 = CorElementType.I4,
970 UInt32 = CorElementType.U4,
971 Int64 = CorElementType.I8,
972 UInt64 = CorElementType.U8,
973 Float = CorElementType.R4,
974 Double = CorElementType.R8,
975 String = CorElementType.String,
976 Array = CorElementType.SzArray,
984 [StructLayout(LayoutKind.Auto)]
985 internal struct CustomAttributeEncodedArgument
988 [MethodImplAttribute(MethodImplOptions.InternalCall)]
989 private static extern void ParseAttributeArguments(
992 ref CustomAttributeCtorParameter[] CustomAttributeCtorParameters,
993 ref CustomAttributeNamedParameter[] CustomAttributeTypedArgument,
994 RuntimeAssembly assembly);
996 internal static void ParseAttributeArguments(ConstArray attributeBlob,
997 ref CustomAttributeCtorParameter[] customAttributeCtorParameters,
998 ref CustomAttributeNamedParameter[] customAttributeNamedParameters,
999 RuntimeModule customAttributeModule)
1001 if (customAttributeModule == null)
1002 throw new ArgumentNullException(nameof(customAttributeModule));
1004 Debug.Assert(customAttributeCtorParameters != null);
1005 Debug.Assert(customAttributeNamedParameters != null);
1007 if (customAttributeCtorParameters.Length != 0 || customAttributeNamedParameters.Length != 0)
1011 ParseAttributeArguments(
1012 attributeBlob.Signature,
1013 (int)attributeBlob.Length,
1014 ref customAttributeCtorParameters,
1015 ref customAttributeNamedParameters,
1016 (RuntimeAssembly)customAttributeModule.Assembly);
1022 #region Private Data Members
1023 private long m_primitiveValue;
1024 private CustomAttributeEncodedArgument[] m_arrayValue;
1025 private string m_stringValue;
1026 private CustomAttributeType m_type;
1029 #region Public Members
1030 public CustomAttributeType CustomAttributeType { get { return m_type; } }
1031 public long PrimitiveValue { get { return m_primitiveValue; } }
1032 public CustomAttributeEncodedArgument[] ArrayValue { get { return m_arrayValue; } }
1033 public string StringValue { get { return m_stringValue; } }
1037 [StructLayout(LayoutKind.Auto)]
1038 internal struct CustomAttributeNamedParameter
1040 #region Private Data Members
1041 private string m_argumentName;
1042 private CustomAttributeEncoding m_fieldOrProperty;
1043 private CustomAttributeEncoding m_padding;
1044 private CustomAttributeType m_type;
1045 private CustomAttributeEncodedArgument m_encodedArgument;
1049 public CustomAttributeNamedParameter(string argumentName, CustomAttributeEncoding fieldOrProperty, CustomAttributeType type)
1051 if (argumentName == null)
1052 throw new ArgumentNullException(nameof(argumentName));
1054 m_argumentName = argumentName;
1055 m_fieldOrProperty = fieldOrProperty;
1056 m_padding = fieldOrProperty;
1058 m_encodedArgument = new CustomAttributeEncodedArgument();
1062 #region Public Members
1063 public CustomAttributeEncodedArgument EncodedArgument { get { return m_encodedArgument; } }
1067 [StructLayout(LayoutKind.Auto)]
1068 internal struct CustomAttributeCtorParameter
1070 #region Private Data Members
1071 private CustomAttributeType m_type;
1072 private CustomAttributeEncodedArgument m_encodedArgument;
1076 public CustomAttributeCtorParameter(CustomAttributeType type)
1079 m_encodedArgument = new CustomAttributeEncodedArgument();
1083 #region Public Members
1084 public CustomAttributeEncodedArgument CustomAttributeEncodedArgument { get { return m_encodedArgument; } }
1088 [StructLayout(LayoutKind.Auto)]
1089 internal struct CustomAttributeType
1091 #region Private Data Members
1092 /// The most complicated type is an enum[] in which case...
1093 private string m_enumName; // ...enum name
1094 private CustomAttributeEncoding m_encodedType; // ...array
1095 private CustomAttributeEncoding m_encodedEnumType; // ...enum
1096 private CustomAttributeEncoding m_encodedArrayType; // ...enum type
1097 private CustomAttributeEncoding m_padding;
1101 public CustomAttributeType(CustomAttributeEncoding encodedType, CustomAttributeEncoding encodedArrayType,
1102 CustomAttributeEncoding encodedEnumType, string enumName)
1104 m_encodedType = encodedType;
1105 m_encodedArrayType = encodedArrayType;
1106 m_encodedEnumType = encodedEnumType;
1107 m_enumName = enumName;
1108 m_padding = m_encodedType;
1112 #region Public Members
1113 public CustomAttributeEncoding EncodedType { get { return m_encodedType; } }
1114 public CustomAttributeEncoding EncodedEnumType { get { return m_encodedEnumType; } }
1115 public CustomAttributeEncoding EncodedArrayType { get { return m_encodedArrayType; } }
1116 public string EnumName { get { return m_enumName; } }
1120 internal unsafe static class CustomAttribute
1122 #region Private Data Members
1123 private static RuntimeType Type_RuntimeType = (RuntimeType)typeof(RuntimeType);
1124 private static RuntimeType Type_Type = (RuntimeType)typeof(Type);
1127 #region Internal Static Members
1128 internal static bool IsDefined(RuntimeType type, RuntimeType caType, bool inherit)
1130 Debug.Assert(type != null);
1132 if (type.GetElementType() != null)
1135 if (PseudoCustomAttribute.IsDefined(type, caType))
1138 if (IsCustomAttributeDefined(type.GetRuntimeModule(), type.MetadataToken, caType))
1144 type = type.BaseType as RuntimeType;
1146 while (type != null)
1148 if (IsCustomAttributeDefined(type.GetRuntimeModule(), type.MetadataToken, caType, 0, inherit))
1151 type = type.BaseType as RuntimeType;
1157 internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType, bool inherit)
1159 Debug.Assert(method != null);
1160 Debug.Assert(caType != null);
1162 if (PseudoCustomAttribute.IsDefined(method, caType))
1165 if (IsCustomAttributeDefined(method.GetRuntimeModule(), method.MetadataToken, caType))
1171 method = method.GetParentDefinition();
1173 while (method != null)
1175 if (IsCustomAttributeDefined(method.GetRuntimeModule(), method.MetadataToken, caType, 0, inherit))
1178 method = method.GetParentDefinition();
1184 internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType)
1186 Debug.Assert(ctor != null);
1187 Debug.Assert(caType != null);
1189 if (PseudoCustomAttribute.IsDefined(ctor, caType))
1192 return IsCustomAttributeDefined(ctor.GetRuntimeModule(), ctor.MetadataToken, caType);
1195 internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType)
1197 Debug.Assert(property != null);
1198 Debug.Assert(caType != null);
1200 if (PseudoCustomAttribute.IsDefined(property, caType))
1203 return IsCustomAttributeDefined(property.GetRuntimeModule(), property.MetadataToken, caType);
1206 internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType)
1208 Debug.Assert(e != null);
1209 Debug.Assert(caType != null);
1211 if (PseudoCustomAttribute.IsDefined(e, caType))
1214 return IsCustomAttributeDefined(e.GetRuntimeModule(), e.MetadataToken, caType);
1217 internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType)
1219 Debug.Assert(field != null);
1220 Debug.Assert(caType != null);
1222 if (PseudoCustomAttribute.IsDefined(field, caType))
1225 return IsCustomAttributeDefined(field.GetRuntimeModule(), field.MetadataToken, caType);
1228 internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType)
1230 Debug.Assert(parameter != null);
1231 Debug.Assert(caType != null);
1233 if (PseudoCustomAttribute.IsDefined(parameter, caType))
1236 return IsCustomAttributeDefined(parameter.GetRuntimeModule(), parameter.MetadataToken, caType);
1239 internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType)
1241 Debug.Assert(assembly != null);
1242 Debug.Assert(caType != null);
1244 if (PseudoCustomAttribute.IsDefined(assembly, caType))
1247 return IsCustomAttributeDefined(assembly.ManifestModule as RuntimeModule, RuntimeAssembly.GetToken(assembly.GetNativeHandle()), caType);
1250 internal static bool IsDefined(RuntimeModule module, RuntimeType caType)
1252 Debug.Assert(module != null);
1253 Debug.Assert(caType != null);
1255 if (PseudoCustomAttribute.IsDefined(module, caType))
1258 return IsCustomAttributeDefined(module, module.MetadataToken, caType);
1261 internal static Object[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool inherit)
1263 Debug.Assert(type != null);
1264 Debug.Assert(caType != null);
1266 if (type.GetElementType() != null)
1267 return (caType.IsValueType) ? Array.Empty<Object>() : CreateAttributeArrayHelper(caType, 0);
1269 if (type.IsGenericType && !type.IsGenericTypeDefinition)
1270 type = type.GetGenericTypeDefinition() as RuntimeType;
1273 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(type, caType, out pcaCount);
1275 // if we are asked to go up the hierarchy chain we have to do it now and regardless of the
1276 // attribute usage for the specific attribute because a derived attribute may override the usage...
1277 // ... however if the attribute is sealed we can rely on the attribute usage
1278 if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited))
1280 object[] attributes = GetCustomAttributes(type.GetRuntimeModule(), type.MetadataToken, pcaCount, caType);
1281 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1285 List<object> result = new List<object>();
1286 bool mustBeInheritable = false;
1287 bool useObjectArray = (caType == null || caType.IsValueType || caType.ContainsGenericParameters);
1288 Type arrayType = useObjectArray ? typeof(object) : caType;
1290 while (pcaCount > 0)
1291 result.Add(pca[--pcaCount]);
1293 while (type != (RuntimeType)typeof(object) && type != null)
1295 object[] attributes = GetCustomAttributes(type.GetRuntimeModule(), type.MetadataToken, 0, caType, mustBeInheritable, result);
1296 mustBeInheritable = true;
1297 for (int i = 0; i < attributes.Length; i++)
1298 result.Add(attributes[i]);
1300 type = type.BaseType as RuntimeType;
1303 object[] typedResult = CreateAttributeArrayHelper(arrayType, result.Count);
1304 Array.Copy(result.ToArray(), 0, typedResult, 0, result.Count);
1308 internal static Object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool inherit)
1310 Debug.Assert(method != null);
1311 Debug.Assert(caType != null);
1313 if (method.IsGenericMethod && !method.IsGenericMethodDefinition)
1314 method = method.GetGenericMethodDefinition() as RuntimeMethodInfo;
1317 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(method, caType, out pcaCount);
1319 // if we are asked to go up the hierarchy chain we have to do it now and regardless of the
1320 // attribute usage for the specific attribute because a derived attribute may override the usage...
1321 // ... however if the attribute is sealed we can rely on the attribute usage
1322 if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited))
1324 object[] attributes = GetCustomAttributes(method.GetRuntimeModule(), method.MetadataToken, pcaCount, caType);
1325 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1329 List<object> result = new List<object>();
1330 bool mustBeInheritable = false;
1331 bool useObjectArray = (caType == null || caType.IsValueType || caType.ContainsGenericParameters);
1332 Type arrayType = useObjectArray ? typeof(object) : caType;
1334 while (pcaCount > 0)
1335 result.Add(pca[--pcaCount]);
1337 while (method != null)
1339 object[] attributes = GetCustomAttributes(method.GetRuntimeModule(), method.MetadataToken, 0, caType, mustBeInheritable, result);
1340 mustBeInheritable = true;
1341 for (int i = 0; i < attributes.Length; i++)
1342 result.Add(attributes[i]);
1344 method = method.GetParentDefinition();
1347 object[] typedResult = CreateAttributeArrayHelper(arrayType, result.Count);
1348 Array.Copy(result.ToArray(), 0, typedResult, 0, result.Count);
1352 internal static Object[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType)
1354 Debug.Assert(ctor != null);
1355 Debug.Assert(caType != null);
1358 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(ctor, caType, out pcaCount);
1359 object[] attributes = GetCustomAttributes(ctor.GetRuntimeModule(), ctor.MetadataToken, pcaCount, caType);
1360 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1364 internal static Object[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType)
1366 Debug.Assert(property != null);
1367 Debug.Assert(caType != null);
1370 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(property, caType, out pcaCount);
1372 object[] attributes = GetCustomAttributes(property.GetRuntimeModule(), property.MetadataToken, pcaCount, caType);
1373 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1377 internal static Object[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType)
1379 Debug.Assert(e != null);
1380 Debug.Assert(caType != null);
1383 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(e, caType, out pcaCount);
1384 object[] attributes = GetCustomAttributes(e.GetRuntimeModule(), e.MetadataToken, pcaCount, caType);
1385 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1389 internal static Object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType)
1391 Debug.Assert(field != null);
1392 Debug.Assert(caType != null);
1395 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(field, caType, out pcaCount);
1396 object[] attributes = GetCustomAttributes(field.GetRuntimeModule(), field.MetadataToken, pcaCount, caType);
1397 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1401 internal static Object[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType)
1403 Debug.Assert(parameter != null);
1404 Debug.Assert(caType != null);
1407 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(parameter, caType, out pcaCount);
1408 object[] attributes = GetCustomAttributes(parameter.GetRuntimeModule(), parameter.MetadataToken, pcaCount, caType);
1409 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1413 internal static Object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType)
1415 Debug.Assert(assembly != null);
1416 Debug.Assert(caType != null);
1419 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(assembly, caType, out pcaCount);
1420 int assemblyToken = RuntimeAssembly.GetToken(assembly.GetNativeHandle());
1421 object[] attributes = GetCustomAttributes(assembly.ManifestModule as RuntimeModule, assemblyToken, pcaCount, caType);
1422 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1426 internal static Object[] GetCustomAttributes(RuntimeModule module, RuntimeType caType)
1428 Debug.Assert(module != null);
1429 Debug.Assert(caType != null);
1432 Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(module, caType, out pcaCount);
1433 object[] attributes = GetCustomAttributes(module, module.MetadataToken, pcaCount, caType);
1434 if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
1438 internal static bool IsAttributeDefined(RuntimeModule decoratedModule, int decoratedMetadataToken, int attributeCtorToken)
1440 return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, null, attributeCtorToken, false);
1443 private static bool IsCustomAttributeDefined(
1444 RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType)
1446 return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, attributeFilterType, 0, false);
1449 private static bool IsCustomAttributeDefined(
1450 RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType, int attributeCtorToken, bool mustBeInheritable)
1452 if (decoratedModule.Assembly.ReflectionOnly)
1453 throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA);
1455 CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken);
1457 if (attributeFilterType != null)
1459 Debug.Assert(attributeCtorToken == 0);
1461 MetadataImport scope = decoratedModule.MetadataImport;
1462 RuntimeType attributeType;
1463 IRuntimeMethodInfo ctor;
1464 bool ctorHasParameters, isVarArg;
1466 // Optimization for the case where attributes decorate entities in the same assembly in which case
1467 // we can cache the successful APTCA check between the decorated and the declared assembly.
1468 Assembly lastAptcaOkAssembly = null;
1470 for (int i = 0; i < car.Length; i++)
1472 CustomAttributeRecord caRecord = car[i];
1474 if (FilterCustomAttributeRecord(caRecord, scope, ref lastAptcaOkAssembly,
1475 decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable, null, null,
1476 out attributeType, out ctor, out ctorHasParameters, out isVarArg))
1482 Debug.Assert(attributeFilterType == null);
1483 Debug.Assert(!MetadataToken.IsNullToken(attributeCtorToken));
1485 for (int i = 0; i < car.Length; i++)
1487 CustomAttributeRecord caRecord = car[i];
1489 if (caRecord.tkCtor == attributeCtorToken)
1497 private unsafe static object[] GetCustomAttributes(
1498 RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType)
1500 return GetCustomAttributes(decoratedModule, decoratedMetadataToken, pcaCount, attributeFilterType, false, null);
1503 private unsafe static object[] GetCustomAttributes(
1504 RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount,
1505 RuntimeType attributeFilterType, bool mustBeInheritable, IList derivedAttributes)
1507 if (decoratedModule.Assembly.ReflectionOnly)
1508 throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA);
1510 MetadataImport scope = decoratedModule.MetadataImport;
1511 CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken);
1513 bool useObjectArray = (attributeFilterType == null || attributeFilterType.IsValueType || attributeFilterType.ContainsGenericParameters);
1514 Type arrayType = useObjectArray ? typeof(object) : attributeFilterType;
1516 if (attributeFilterType == null && car.Length == 0)
1517 return CreateAttributeArrayHelper(arrayType, 0);
1519 object[] attributes = CreateAttributeArrayHelper(arrayType, car.Length);
1520 int cAttributes = 0;
1522 // Optimization for the case where attributes decorate entities in the same assembly in which case
1523 // we can cache the successful APTCA check between the decorated and the declared assembly.
1524 Assembly lastAptcaOkAssembly = null;
1526 for (int i = 0; i < car.Length; i++)
1528 object attribute = null;
1529 CustomAttributeRecord caRecord = car[i];
1531 IRuntimeMethodInfo ctor = null;
1532 RuntimeType attributeType = null;
1533 bool ctorHasParameters, isVarArg;
1536 IntPtr blobStart = caRecord.blob.Signature;
1537 IntPtr blobEnd = (IntPtr)((byte*)blobStart + caRecord.blob.Length);
1538 int blobLen = (int)((byte*)blobEnd - (byte*)blobStart);
1540 if (!FilterCustomAttributeRecord(caRecord, scope, ref lastAptcaOkAssembly,
1541 decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable,
1542 attributes, derivedAttributes,
1543 out attributeType, out ctor, out ctorHasParameters, out isVarArg))
1546 // Leverage RuntimeConstructorInfo standard .ctor verfication
1547 RuntimeConstructorInfo.CheckCanCreateInstance(attributeType, isVarArg);
1549 // Create custom attribute object
1550 if (ctorHasParameters)
1552 attribute = CreateCaObject(decoratedModule, ctor, ref blobStart, blobEnd, out cNamedArgs);
1556 attribute = RuntimeTypeHandle.CreateCaInstance(attributeType, ctor);
1558 // It is allowed by the ECMA spec to have an empty signature blob
1563 // Metadata is always written in little-endian format. Must account for this on
1564 // big-endian platforms.
1566 const int CustomAttributeVersion = 0x0100;
1568 const int CustomAttributeVersion = 0x0001;
1570 if (Marshal.ReadInt16(blobStart) != CustomAttributeVersion)
1571 throw new CustomAttributeFormatException();
1572 blobStart = (IntPtr)((byte*)blobStart + 2); // skip version prefix
1574 cNamedArgs = Marshal.ReadInt16(blobStart);
1575 blobStart = (IntPtr)((byte*)blobStart + 2); // skip namedArgs count
1577 cNamedArgs = ((cNamedArgs & 0xff00) >> 8) | ((cNamedArgs & 0x00ff) << 8);
1582 for (int j = 0; j < cNamedArgs; j++)
1584 #region // Initialize named properties and fields
1590 IntPtr blobItr = caRecord.blob.Signature;
1592 GetPropertyOrFieldData(decoratedModule, ref blobStart, blobEnd, out name, out isProperty, out type, out value);
1598 #region // Initialize property
1599 if (type == null && value != null)
1601 type = (RuntimeType)value.GetType();
1602 if (type == Type_RuntimeType)
1606 RuntimePropertyInfo property = null;
1609 property = attributeType.GetProperty(name) as RuntimePropertyInfo;
1611 property = attributeType.GetProperty(name, type, Type.EmptyTypes) as RuntimePropertyInfo;
1613 // Did we get a valid property reference?
1614 if (property == null)
1616 throw new CustomAttributeFormatException(
1617 String.Format(CultureInfo.CurrentUICulture,
1618 isProperty ? SR.RFLCT_InvalidPropFail : SR.RFLCT_InvalidFieldFail, name));
1621 RuntimeMethodInfo setMethod = property.GetSetMethod(true) as RuntimeMethodInfo;
1623 // Public properties may have non-public setter methods
1624 if (!setMethod.IsPublic)
1627 setMethod.UnsafeInvoke(attribute, BindingFlags.Default, null, new object[] { value }, null);
1632 RtFieldInfo field = attributeType.GetField(name) as RtFieldInfo;
1634 field.CheckConsistency(attribute);
1635 field.UnsafeSetValue(attribute, value, BindingFlags.Default, Type.DefaultBinder, null);
1640 throw new CustomAttributeFormatException(
1641 String.Format(CultureInfo.CurrentUICulture,
1642 isProperty ? SR.RFLCT_InvalidPropFail : SR.RFLCT_InvalidFieldFail, name), e);
1647 if (blobStart != blobEnd)
1648 throw new CustomAttributeFormatException();
1650 attributes[cAttributes++] = attribute;
1653 if (cAttributes == car.Length && pcaCount == 0)
1656 object[] result = CreateAttributeArrayHelper(arrayType, cAttributes + pcaCount);
1657 Array.Copy(attributes, 0, result, 0, cAttributes);
1661 private unsafe static bool FilterCustomAttributeRecord(
1662 CustomAttributeRecord caRecord,
1663 MetadataImport scope,
1664 ref Assembly lastAptcaOkAssembly,
1665 RuntimeModule decoratedModule,
1666 MetadataToken decoratedToken,
1667 RuntimeType attributeFilterType,
1668 bool mustBeInheritable,
1669 object[] attributes,
1670 IList derivedAttributes,
1671 out RuntimeType attributeType,
1672 out IRuntimeMethodInfo ctor,
1673 out bool ctorHasParameters,
1677 attributeType = null;
1678 ctorHasParameters = false;
1681 IntPtr blobStart = caRecord.blob.Signature;
1682 IntPtr blobEnd = (IntPtr)((byte*)blobStart + caRecord.blob.Length);
1684 // Resolve attribute type from ctor parent token found in decorated decoratedModule scope
1685 attributeType = decoratedModule.ResolveType(scope.GetParentToken(caRecord.tkCtor), null, null) as RuntimeType;
1688 // Test attribute type against user provided attribute type filter
1689 if (!(attributeFilterType.IsAssignableFrom(attributeType)))
1692 // Ensure if attribute type must be inheritable that it is inhertiable
1693 // Ensure that to consider a duplicate attribute type AllowMultiple is true
1694 if (!AttributeUsageCheck(attributeType, mustBeInheritable, attributes, derivedAttributes))
1697 // Windows Runtime attributes aren't real types - they exist to be read as metadata only, and as such
1698 // should be filtered out of the GetCustomAttributes path.
1699 if ((attributeType.Attributes & TypeAttributes.WindowsRuntime) == TypeAttributes.WindowsRuntime)
1704 // Resolve the attribute ctor
1705 ConstArray ctorSig = scope.GetMethodSignature(caRecord.tkCtor);
1706 isVarArg = (ctorSig[0] & 0x05) != 0;
1707 ctorHasParameters = ctorSig[1] != 0;
1709 if (ctorHasParameters)
1711 // Resolve method ctor token found in decorated decoratedModule scope
1712 ctor = ModuleHandle.ResolveMethodHandleInternal(decoratedModule.GetNativeHandle(), caRecord.tkCtor);
1716 // Resolve method ctor token from decorated decoratedModule scope
1717 ctor = attributeType.GetTypeHandleInternal().GetDefaultConstructor();
1719 if (ctor == null && !attributeType.IsValueType)
1720 throw new MissingMethodException(".ctor");
1723 // Visibility checks
1724 MetadataToken tkParent = new MetadataToken();
1726 if (decoratedToken.IsParamDef)
1728 tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
1729 tkParent = new MetadataToken(scope.GetParentToken(tkParent));
1731 else if (decoratedToken.IsMethodDef || decoratedToken.IsProperty || decoratedToken.IsEvent || decoratedToken.IsFieldDef)
1733 tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
1735 else if (decoratedToken.IsTypeDef)
1737 tkParent = decoratedToken;
1739 else if (decoratedToken.IsGenericPar)
1741 tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
1743 // decoratedToken is a generic parameter on a method. Get the declaring Type of the method.
1744 if (tkParent.IsMethodDef)
1745 tkParent = new MetadataToken(scope.GetParentToken(tkParent));
1749 // We need to relax this when we add support for other types of decorated tokens.
1750 Debug.Assert(decoratedToken.IsModule || decoratedToken.IsAssembly,
1751 "The decoratedToken must be either an assembly, a module, a type, or a member.");
1754 // If the attribute is on a type, member, or parameter we check access against the (declaring) type,
1755 // otherwise we check access against the module.
1756 RuntimeTypeHandle parentTypeHandle = tkParent.IsTypeDef ?
1757 decoratedModule.ModuleHandle.ResolveTypeHandle(tkParent) :
1758 new RuntimeTypeHandle();
1760 return RuntimeMethodHandle.IsCAVisibleFromDecoratedType(attributeType.TypeHandle, ctor, parentTypeHandle, decoratedModule);
1764 #region Private Static Methods
1765 private static bool AttributeUsageCheck(
1766 RuntimeType attributeType, bool mustBeInheritable, object[] attributes, IList derivedAttributes)
1768 AttributeUsageAttribute attributeUsageAttribute = null;
1770 if (mustBeInheritable)
1772 attributeUsageAttribute = CustomAttribute.GetAttributeUsage(attributeType);
1774 if (!attributeUsageAttribute.Inherited)
1778 // Legacy: AllowMultiple ignored for none inheritable attributes
1780 if (derivedAttributes == null)
1783 for (int i = 0; i < derivedAttributes.Count; i++)
1785 if (derivedAttributes[i].GetType() == attributeType)
1787 if (attributeUsageAttribute == null)
1788 attributeUsageAttribute = CustomAttribute.GetAttributeUsage(attributeType);
1790 return attributeUsageAttribute.AllowMultiple;
1797 internal static AttributeUsageAttribute GetAttributeUsage(RuntimeType decoratedAttribute)
1799 RuntimeModule decoratedModule = decoratedAttribute.GetRuntimeModule();
1800 MetadataImport scope = decoratedModule.MetadataImport;
1801 CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedAttribute.MetadataToken);
1803 AttributeUsageAttribute attributeUsageAttribute = null;
1805 for (int i = 0; i < car.Length; i++)
1807 CustomAttributeRecord caRecord = car[i];
1808 RuntimeType attributeType = decoratedModule.ResolveType(scope.GetParentToken(caRecord.tkCtor), null, null) as RuntimeType;
1810 if (attributeType != (RuntimeType)typeof(AttributeUsageAttribute))
1813 if (attributeUsageAttribute != null)
1814 throw new FormatException(String.Format(
1815 CultureInfo.CurrentUICulture, SR.Format_AttributeUsage, attributeType));
1817 AttributeTargets targets;
1818 bool inherited, allowMultiple;
1819 ParseAttributeUsageAttribute(caRecord.blob, out targets, out inherited, out allowMultiple);
1820 attributeUsageAttribute = new AttributeUsageAttribute(targets, allowMultiple, inherited);
1823 if (attributeUsageAttribute == null)
1824 return AttributeUsageAttribute.Default;
1826 return attributeUsageAttribute;
1830 #region Private Static FCalls
1831 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1832 private static extern void _ParseAttributeUsageAttribute(
1833 IntPtr pCa, int cCa, out int targets, out bool inherited, out bool allowMultiple);
1834 private static void ParseAttributeUsageAttribute(
1835 ConstArray ca, out AttributeTargets targets, out bool inherited, out bool allowMultiple)
1838 _ParseAttributeUsageAttribute(ca.Signature, ca.Length, out _targets, out inherited, out allowMultiple);
1839 targets = (AttributeTargets)_targets;
1842 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1843 private static unsafe extern Object _CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, byte** ppBlob, byte* pEndBlob, int* pcNamedArgs);
1844 private static unsafe Object CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, ref IntPtr blob, IntPtr blobEnd, out int namedArgs)
1846 byte* pBlob = (byte*)blob;
1847 byte* pBlobEnd = (byte*)blobEnd;
1849 object ca = _CreateCaObject(module, ctor, &pBlob, pBlobEnd, &cNamedArgs);
1850 blob = (IntPtr)pBlob;
1851 namedArgs = cNamedArgs;
1855 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1856 private unsafe extern static void _GetPropertyOrFieldData(
1857 RuntimeModule pModule, byte** ppBlobStart, byte* pBlobEnd, out string name, out bool bIsProperty, out RuntimeType type, out object value);
1858 private unsafe static void GetPropertyOrFieldData(
1859 RuntimeModule module, ref IntPtr blobStart, IntPtr blobEnd, out string name, out bool isProperty, out RuntimeType type, out object value)
1861 byte* pBlobStart = (byte*)blobStart;
1862 _GetPropertyOrFieldData(
1863 module.GetNativeHandle(), &pBlobStart, (byte*)blobEnd, out name, out isProperty, out type, out value);
1864 blobStart = (IntPtr)pBlobStart;
1867 private static object[] CreateAttributeArrayHelper(Type elementType, int elementCount)
1869 return (object[])Array.UnsafeCreateInstance(elementType, elementCount);
1874 internal static class PseudoCustomAttribute
1876 #region Private Static Data Members
1877 // Here we can avoid the need to take a lock when using Dictionary by rearranging
1878 // the only method that adds values to the Dictionary. For more details on
1879 // Dictionary versus Hashtable thread safety:
1880 // See code:Dictionary#DictionaryVersusHashtableThreadSafety
1881 private static Dictionary<RuntimeType, RuntimeType> s_pca;
1882 private static int s_pcasCount;
1885 #region Static Constructor
1886 static PseudoCustomAttribute()
1888 RuntimeType[] pcas = new RuntimeType[]
1890 // See //depot/DevDiv/private/Main/ndp/clr/src/MD/Compiler/CustAttr.cpp
1891 typeof(FieldOffsetAttribute) as RuntimeType, // field
1892 typeof(SerializableAttribute) as RuntimeType, // class, struct, enum, delegate
1893 typeof(MarshalAsAttribute) as RuntimeType, // parameter, field, return-value
1894 typeof(ComImportAttribute) as RuntimeType, // class, interface
1895 typeof(NonSerializedAttribute) as RuntimeType, // field, inherited
1896 typeof(InAttribute) as RuntimeType, // parameter
1897 typeof(OutAttribute) as RuntimeType, // parameter
1898 typeof(OptionalAttribute) as RuntimeType, // parameter
1899 typeof(DllImportAttribute) as RuntimeType, // method
1900 typeof(PreserveSigAttribute) as RuntimeType, // method
1901 typeof(TypeForwardedToAttribute) as RuntimeType, // assembly
1904 s_pcasCount = pcas.Length;
1905 Dictionary<RuntimeType, RuntimeType> temp_pca = new Dictionary<RuntimeType, RuntimeType>(s_pcasCount);
1907 for (int i = 0; i < s_pcasCount; i++)
1909 VerifyPseudoCustomAttribute(pcas[i]);
1910 temp_pca[pcas[i]] = pcas[i];
1915 [Conditional("DEBUG")]
1916 private static void VerifyPseudoCustomAttribute(RuntimeType pca)
1918 // If any of these are invariants are no longer true will have to
1919 // re-architect the PCA product logic and test cases -- you've been warned!
1920 Debug.Assert(pca.BaseType == (RuntimeType)typeof(Attribute), "Pseudo CA Error");
1921 AttributeUsageAttribute usage = CustomAttribute.GetAttributeUsage(pca);
1922 Debug.Assert(usage.Inherited == false, "Pseudo CA Error");
1923 //AllowMultiple is true for TypeForwardedToAttribute
1924 //Debug.Assert(usage.AllowMultiple == false, "Pseudo CA Error");
1928 #region Internal Static
1929 internal static Attribute[] GetCustomAttributes(RuntimeType type, RuntimeType caType, out int count)
1931 Debug.Assert(type != null);
1932 Debug.Assert(caType != null);
1936 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
1937 if (!all && !s_pca.ContainsKey(caType))
1938 return Array.Empty<Attribute>();
1940 List<Attribute> pcas = new List<Attribute>();
1942 if (all || caType == (RuntimeType)typeof(SerializableAttribute))
1944 if ((type.Attributes & TypeAttributes.Serializable) != 0)
1945 pcas.Add(new SerializableAttribute());
1947 if (all || caType == (RuntimeType)typeof(ComImportAttribute))
1949 if ((type.Attributes & TypeAttributes.Import) != 0)
1950 pcas.Add(new ComImportAttribute());
1954 return pcas.ToArray();
1956 internal static bool IsDefined(RuntimeType type, RuntimeType caType)
1958 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
1959 if (!all && !s_pca.ContainsKey(caType))
1962 if (all || caType == (RuntimeType)typeof(SerializableAttribute))
1964 if ((type.Attributes & TypeAttributes.Serializable) != 0)
1967 if (all || caType == (RuntimeType)typeof(ComImportAttribute))
1969 if ((type.Attributes & TypeAttributes.Import) != 0)
1976 internal static Attribute[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, out int count)
1978 Debug.Assert(method != null);
1979 Debug.Assert(caType != null);
1983 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
1984 if (!all && !s_pca.ContainsKey(caType))
1985 return Array.Empty<Attribute>();
1987 List<Attribute> pcas = new List<Attribute>();
1990 if (all || caType == (RuntimeType)typeof(DllImportAttribute))
1992 pca = GetDllImportCustomAttribute(method);
1993 if (pca != null) pcas[count++] = pca;
1995 if (all || caType == (RuntimeType)typeof(PreserveSigAttribute))
1997 if ((method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0)
1998 pcas.Add(new PreserveSigAttribute());
2002 return pcas.ToArray();
2004 internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType)
2006 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
2007 if (!all && !s_pca.ContainsKey(caType))
2010 if (all || caType == (RuntimeType)typeof(DllImportAttribute))
2012 if ((method.Attributes & MethodAttributes.PinvokeImpl) != 0)
2015 if (all || caType == (RuntimeType)typeof(PreserveSigAttribute))
2017 if ((method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0)
2024 internal static Attribute[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, out int count)
2026 Debug.Assert(parameter != null);
2027 Debug.Assert(caType != null);
2031 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
2032 if (!all && !s_pca.ContainsKey(caType))
2035 Attribute[] pcas = new Attribute[s_pcasCount];
2038 if (all || caType == (RuntimeType)typeof(InAttribute))
2041 pcas[count++] = new InAttribute();
2043 if (all || caType == (RuntimeType)typeof(OutAttribute))
2045 if (parameter.IsOut)
2046 pcas[count++] = new OutAttribute();
2048 if (all || caType == (RuntimeType)typeof(OptionalAttribute))
2050 if (parameter.IsOptional)
2051 pcas[count++] = new OptionalAttribute();
2053 if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
2055 pca = GetMarshalAsCustomAttribute(parameter);
2056 if (pca != null) pcas[count++] = pca;
2060 internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType)
2062 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
2063 if (!all && !s_pca.ContainsKey(caType))
2067 if (all || caType == (RuntimeType)typeof(InAttribute))
2069 if (parameter.IsIn) return true;
2071 if (all || caType == (RuntimeType)typeof(OutAttribute))
2073 if (parameter.IsOut) return true;
2075 if (all || caType == (RuntimeType)typeof(OptionalAttribute))
2077 if (parameter.IsOptional) return true;
2079 if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
2081 if (GetMarshalAsCustomAttribute(parameter) != null) return true;
2087 internal static Attribute[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType, out int count)
2092 internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType)
2097 internal static Attribute[] GetCustomAttributes(RuntimeModule module, RuntimeType caType, out int count)
2102 internal static bool IsDefined(RuntimeModule module, RuntimeType caType)
2107 internal static Attribute[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, out int count)
2109 Debug.Assert(field != null);
2110 Debug.Assert(caType != null);
2114 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
2115 if (!all && !s_pca.ContainsKey(caType))
2118 Attribute[] pcas = new Attribute[s_pcasCount];
2121 if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
2123 pca = GetMarshalAsCustomAttribute(field);
2124 if (pca != null) pcas[count++] = pca;
2126 if (all || caType == (RuntimeType)typeof(FieldOffsetAttribute))
2128 pca = GetFieldOffsetCustomAttribute(field);
2129 if (pca != null) pcas[count++] = pca;
2131 if (all || caType == (RuntimeType)typeof(NonSerializedAttribute))
2133 if ((field.Attributes & FieldAttributes.NotSerialized) != 0)
2134 pcas[count++] = new NonSerializedAttribute();
2138 internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType)
2140 bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
2141 if (!all && !s_pca.ContainsKey(caType))
2144 if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
2146 if (GetMarshalAsCustomAttribute(field) != null) return true;
2148 if (all || caType == (RuntimeType)typeof(FieldOffsetAttribute))
2150 if (GetFieldOffsetCustomAttribute(field) != null) return true;
2152 if (all || caType == (RuntimeType)typeof(NonSerializedAttribute))
2154 if ((field.Attributes & FieldAttributes.NotSerialized) != 0)
2161 internal static Attribute[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType, out int count)
2166 internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType)
2171 internal static Attribute[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType, out int count)
2176 internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType)
2181 internal static Attribute[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType, out int count)
2186 internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType)
2192 private static DllImportAttribute GetDllImportCustomAttribute(RuntimeMethodInfo method)
2194 if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0)
2197 MetadataImport scope = ModuleHandle.GetMetadataImport(method.Module.ModuleHandle.GetRuntimeModule());
2198 string entryPoint, dllName = null;
2199 int token = method.MetadataToken;
2200 PInvokeAttributes flags = 0;
2202 scope.GetPInvokeMap(token, out flags, out entryPoint, out dllName);
2204 CharSet charSet = CharSet.None;
2206 switch (flags & PInvokeAttributes.CharSetMask)
2208 case PInvokeAttributes.CharSetNotSpec: charSet = CharSet.None; break;
2209 case PInvokeAttributes.CharSetAnsi: charSet = CharSet.Ansi; break;
2210 case PInvokeAttributes.CharSetUnicode: charSet = CharSet.Unicode; break;
2211 case PInvokeAttributes.CharSetAuto: charSet = CharSet.Auto; break;
2213 // Invalid: default to CharSet.None
2217 CallingConvention callingConvention = CallingConvention.Cdecl;
2219 switch (flags & PInvokeAttributes.CallConvMask)
2221 case PInvokeAttributes.CallConvWinapi: callingConvention = CallingConvention.Winapi; break;
2222 case PInvokeAttributes.CallConvCdecl: callingConvention = CallingConvention.Cdecl; break;
2223 case PInvokeAttributes.CallConvStdcall: callingConvention = CallingConvention.StdCall; break;
2224 case PInvokeAttributes.CallConvThiscall: callingConvention = CallingConvention.ThisCall; break;
2225 case PInvokeAttributes.CallConvFastcall: callingConvention = CallingConvention.FastCall; break;
2227 // Invalid: default to CallingConvention.Cdecl
2231 DllImportAttribute attribute = new DllImportAttribute(dllName);
2233 attribute.EntryPoint = entryPoint;
2234 attribute.CharSet = charSet;
2235 attribute.SetLastError = (flags & PInvokeAttributes.SupportsLastError) != 0;
2236 attribute.ExactSpelling = (flags & PInvokeAttributes.NoMangle) != 0;
2237 attribute.PreserveSig = (method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0;
2238 attribute.CallingConvention = callingConvention;
2239 attribute.BestFitMapping = (flags & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitEnabled;
2240 attribute.ThrowOnUnmappableChar = (flags & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharEnabled;
2246 private static MarshalAsAttribute GetMarshalAsCustomAttribute(RuntimeParameterInfo parameter)
2248 return GetMarshalAsCustomAttribute(parameter.MetadataToken, parameter.GetRuntimeModule());
2250 private static MarshalAsAttribute GetMarshalAsCustomAttribute(RuntimeFieldInfo field)
2252 return GetMarshalAsCustomAttribute(field.MetadataToken, field.GetRuntimeModule());
2255 private static MarshalAsAttribute GetMarshalAsCustomAttribute(int token, RuntimeModule scope)
2257 UnmanagedType unmanagedType, arraySubType;
2258 VarEnum safeArraySubType;
2259 int sizeParamIndex = 0, sizeConst = 0;
2260 string marshalTypeName = null, marshalCookie = null, safeArrayUserDefinedTypeName = null;
2261 int iidParamIndex = 0;
2262 ConstArray nativeType = ModuleHandle.GetMetadataImport(scope.GetNativeHandle()).GetFieldMarshal(token);
2264 if (nativeType.Length == 0)
2267 MetadataImport.GetMarshalAs(nativeType,
2268 out unmanagedType, out safeArraySubType, out safeArrayUserDefinedTypeName, out arraySubType, out sizeParamIndex,
2269 out sizeConst, out marshalTypeName, out marshalCookie, out iidParamIndex);
2271 RuntimeType safeArrayUserDefinedType = safeArrayUserDefinedTypeName == null || safeArrayUserDefinedTypeName.Length == 0 ? null :
2272 RuntimeTypeHandle.GetTypeByNameUsingCARules(safeArrayUserDefinedTypeName, scope);
2273 RuntimeType marshalTypeRef = null;
2277 marshalTypeRef = marshalTypeName == null ? null : RuntimeTypeHandle.GetTypeByNameUsingCARules(marshalTypeName, scope);
2279 catch (System.TypeLoadException)
2281 // The user may have supplied a bad type name string causing this TypeLoadException
2282 // Regardless, we return the bad type name
2283 Debug.Assert(marshalTypeName != null);
2286 MarshalAsAttribute attribute = new MarshalAsAttribute(unmanagedType);
2288 attribute.SafeArraySubType = safeArraySubType;
2289 attribute.SafeArrayUserDefinedSubType = safeArrayUserDefinedType;
2290 attribute.IidParameterIndex = iidParamIndex;
2291 attribute.ArraySubType = arraySubType;
2292 attribute.SizeParamIndex = (short)sizeParamIndex;
2293 attribute.SizeConst = sizeConst;
2294 attribute.MarshalType = marshalTypeName;
2295 attribute.MarshalTypeRef = marshalTypeRef;
2296 attribute.MarshalCookie = marshalCookie;
2301 private static FieldOffsetAttribute GetFieldOffsetCustomAttribute(RuntimeFieldInfo field)
2305 if (field.DeclaringType != null &&
2306 field.GetRuntimeModule().MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out fieldOffset))
2307 return new FieldOffsetAttribute(fieldOffset);
2312 internal static StructLayoutAttribute GetStructLayoutCustomAttribute(RuntimeType type)
2314 if (type.IsInterface || type.HasElementType || type.IsGenericParameter)
2317 int pack = 0, size = 0;
2318 LayoutKind layoutKind = LayoutKind.Auto;
2319 switch (type.Attributes & TypeAttributes.LayoutMask)
2321 case TypeAttributes.ExplicitLayout: layoutKind = LayoutKind.Explicit; break;
2322 case TypeAttributes.AutoLayout: layoutKind = LayoutKind.Auto; break;
2323 case TypeAttributes.SequentialLayout: layoutKind = LayoutKind.Sequential; break;
2324 default: Debug.Fail("Unreachable code"); break;
2327 CharSet charSet = CharSet.None;
2328 switch (type.Attributes & TypeAttributes.StringFormatMask)
2330 case TypeAttributes.AnsiClass: charSet = CharSet.Ansi; break;
2331 case TypeAttributes.AutoClass: charSet = CharSet.Auto; break;
2332 case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break;
2333 default: Debug.Fail("Unreachable code"); break;
2335 type.GetRuntimeModule().MetadataImport.GetClassLayout(type.MetadataToken, out pack, out size);
2337 // Metadata parameter checking should not have allowed 0 for packing size.
2338 // The runtime later converts a packing size of 0 to 8 so do the same here
2339 // because it's more useful from a user perspective.
2341 pack = 8; // DEFAULT_PACKING_SIZE
2343 StructLayoutAttribute attribute = new StructLayoutAttribute(layoutKind);
2345 attribute.Pack = pack;
2346 attribute.Size = size;
2347 attribute.CharSet = charSet;