2 Copyright (C) 2009-2012 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Collections.Generic;
28 using IKVM.Reflection.Reader;
29 using IKVM.Reflection.Emit;
30 using IKVM.Reflection.Metadata;
32 namespace IKVM.Reflection
34 public sealed class CustomAttributeData
36 internal static readonly IList<CustomAttributeData> EmptyList = new List<CustomAttributeData>(0).AsReadOnly();
39 * There are several states a CustomAttributeData object can be in:
41 * 1) Unresolved Custom Attribute
42 * - customAttributeIndex >= 0
43 * - declSecurityIndex == -1
44 * - declSecurityBlob == null
45 * - lazyConstructor = null
46 * - lazyConstructorArguments = null
47 * - lazyNamedArguments = null
49 * 2) Resolved Custom Attribute
50 * - customAttributeIndex >= 0
51 * - declSecurityIndex == -1
52 * - declSecurityBlob == null
53 * - lazyConstructor != null
54 * - lazyConstructorArguments != null
55 * - lazyNamedArguments != null
57 * 3) Pre-resolved Custom Attribute
58 * - customAttributeIndex = -1
59 * - declSecurityIndex == -1
60 * - declSecurityBlob == null
61 * - lazyConstructor != null
62 * - lazyConstructorArguments != null
63 * - lazyNamedArguments != null
65 * 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData()
66 * - customAttributeIndex = -1
67 * - declSecurityIndex == -1
68 * - declSecurityBlob == null
69 * - lazyConstructor != null
70 * - lazyConstructorArguments != null
71 * - lazyNamedArguments != null
73 * 5) Unresolved declarative security
74 * - customAttributeIndex = -1
75 * - declSecurityIndex >= 0
76 * - declSecurityBlob != null
77 * - lazyConstructor != null
78 * - lazyConstructorArguments != null
79 * - lazyNamedArguments == null
81 * 6) Resolved declarative security
82 * - customAttributeIndex = -1
83 * - declSecurityIndex >= 0
84 * - declSecurityBlob == null
85 * - lazyConstructor != null
86 * - lazyConstructorArguments != null
87 * - lazyNamedArguments != null
90 private readonly Module module;
91 private readonly int customAttributeIndex;
92 private readonly int declSecurityIndex;
93 private readonly byte[] declSecurityBlob;
94 private ConstructorInfo lazyConstructor;
95 private IList<CustomAttributeTypedArgument> lazyConstructorArguments;
96 private IList<CustomAttributeNamedArgument> lazyNamedArguments;
98 // 1) Unresolved Custom Attribute
99 internal CustomAttributeData(Module module, int index)
101 this.module = module;
102 this.customAttributeIndex = index;
103 this.declSecurityIndex = -1;
106 // 4) Pseudo Custom Attribute, .NET 1.x declarative security
107 internal CustomAttributeData(Module module, ConstructorInfo constructor, object[] args, List<CustomAttributeNamedArgument> namedArguments)
108 : this(module, constructor, WrapConstructorArgs(args, constructor.MethodSignature), namedArguments)
112 private static List<CustomAttributeTypedArgument> WrapConstructorArgs(object[] args, MethodSignature sig)
114 List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
115 for (int i = 0; i < args.Length; i++)
117 list.Add(new CustomAttributeTypedArgument(sig.GetParameterType(i), args[i]));
122 // 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData()
123 internal CustomAttributeData(Module module, ConstructorInfo constructor, List<CustomAttributeTypedArgument> constructorArgs, List<CustomAttributeNamedArgument> namedArguments)
125 this.module = module;
126 this.customAttributeIndex = -1;
127 this.declSecurityIndex = -1;
128 this.lazyConstructor = constructor;
129 lazyConstructorArguments = constructorArgs.AsReadOnly();
130 if (namedArguments == null)
132 this.lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
136 this.lazyNamedArguments = namedArguments.AsReadOnly();
140 // 3) Pre-resolved Custom Attribute
141 internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, ByteReader br)
143 this.module = asm.ManifestModule;
144 this.customAttributeIndex = -1;
145 this.declSecurityIndex = -1;
146 this.lazyConstructor = constructor;
149 // it's legal to have an empty blob
150 lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
151 lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
155 if (br.ReadUInt16() != 1)
157 throw new BadImageFormatException();
159 lazyConstructorArguments = ReadConstructorArguments(asm, br, constructor);
160 lazyNamedArguments = ReadNamedArguments(asm, br, br.ReadUInt16(), constructor.DeclaringType);
164 public override string ToString()
166 StringBuilder sb = new StringBuilder();
168 sb.Append(Constructor.DeclaringType.FullName);
171 ParameterInfo[] parameters = Constructor.GetParameters();
172 IList<CustomAttributeTypedArgument> args = ConstructorArguments;
173 for (int i = 0; i < parameters.Length; i++)
177 AppendValue(sb, parameters[i].ParameterType, args[i]);
179 foreach (CustomAttributeNamedArgument named in NamedArguments)
183 sb.Append(named.MemberInfo.Name);
185 FieldInfo fi = named.MemberInfo as FieldInfo;
186 Type type = fi != null ? fi.FieldType : ((PropertyInfo)named.MemberInfo).PropertyType;
187 AppendValue(sb, type, named.TypedValue);
191 return sb.ToString();
194 private static void AppendValue(StringBuilder sb, Type type, CustomAttributeTypedArgument arg)
196 if (arg.ArgumentType == arg.ArgumentType.Module.universe.System_String)
198 sb.Append('"').Append(arg.Value).Append('"');
200 else if (arg.ArgumentType.IsArray)
202 Type elementType = arg.ArgumentType.GetElementType();
203 string elementTypeName;
204 if (elementType.IsPrimitive
205 || elementType == type.Module.universe.System_Object
206 || elementType == type.Module.universe.System_String
207 || elementType == type.Module.universe.System_Type)
209 elementTypeName = elementType.Name;
213 elementTypeName = elementType.FullName;
215 sb.Append("new ").Append(elementTypeName).Append("[").Append(((Array)arg.Value).Length).Append("] { ");
217 foreach (CustomAttributeTypedArgument elem in (CustomAttributeTypedArgument[])arg.Value)
221 AppendValue(sb, elementType, elem);
227 if (arg.ArgumentType != type || (type.IsEnum && !arg.Value.Equals(0)))
230 sb.Append(arg.ArgumentType.FullName);
233 sb.Append(arg.Value);
237 internal static void ReadDeclarativeSecurity(Module module, int index, List<CustomAttributeData> list)
239 Universe u = module.universe;
240 Assembly asm = module.Assembly;
241 int action = module.DeclSecurity.records[index].Action;
242 ByteReader br = module.GetBlob(module.DeclSecurity.records[index].PermissionSet);
243 if (br.PeekByte() == '.')
246 int count = br.ReadCompressedUInt();
247 for (int j = 0; j < count; j++)
249 Type type = ReadType(asm, br);
250 ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(u.System_Security_Permissions_SecurityAction);
251 // LAMESPEC there is an additional length here (probably of the named argument list)
252 byte[] blob = br.ReadBytes(br.ReadCompressedUInt());
253 list.Add(new CustomAttributeData(asm, constructor, action, blob, index));
258 // .NET 1.x format (xml)
259 char[] buf = new char[br.Length / 2];
260 for (int i = 0; i < buf.Length; i++)
262 buf[i] = br.ReadChar();
264 string xml = new String(buf);
265 ConstructorInfo constructor = u.System_Security_Permissions_PermissionSetAttribute.GetPseudoCustomAttributeConstructor(u.System_Security_Permissions_SecurityAction);
266 List<CustomAttributeNamedArgument> args = new List<CustomAttributeNamedArgument>();
267 args.Add(new CustomAttributeNamedArgument(GetProperty(u.System_Security_Permissions_PermissionSetAttribute, "XML", u.System_String),
268 new CustomAttributeTypedArgument(u.System_String, xml)));
269 list.Add(new CustomAttributeData(asm.ManifestModule, constructor, new object[] { action }, args));
273 // 5) Unresolved declarative security
274 internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, int securityAction, byte[] blob, int index)
276 this.module = asm.ManifestModule;
277 this.customAttributeIndex = -1;
278 this.declSecurityIndex = index;
279 Universe u = constructor.Module.universe;
280 this.lazyConstructor = constructor;
281 List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>();
282 list.Add(new CustomAttributeTypedArgument(u.System_Security_Permissions_SecurityAction, securityAction));
283 this.lazyConstructorArguments = list.AsReadOnly();
284 this.declSecurityBlob = blob;
287 private static Type ReadFieldOrPropType(Assembly asm, ByteReader br)
289 Universe u = asm.universe;
290 switch (br.ReadByte())
292 case Signature.ELEMENT_TYPE_BOOLEAN:
293 return u.System_Boolean;
294 case Signature.ELEMENT_TYPE_CHAR:
295 return u.System_Char;
296 case Signature.ELEMENT_TYPE_I1:
297 return u.System_SByte;
298 case Signature.ELEMENT_TYPE_U1:
299 return u.System_Byte;
300 case Signature.ELEMENT_TYPE_I2:
301 return u.System_Int16;
302 case Signature.ELEMENT_TYPE_U2:
303 return u.System_UInt16;
304 case Signature.ELEMENT_TYPE_I4:
305 return u.System_Int32;
306 case Signature.ELEMENT_TYPE_U4:
307 return u.System_UInt32;
308 case Signature.ELEMENT_TYPE_I8:
309 return u.System_Int64;
310 case Signature.ELEMENT_TYPE_U8:
311 return u.System_UInt64;
312 case Signature.ELEMENT_TYPE_R4:
313 return u.System_Single;
314 case Signature.ELEMENT_TYPE_R8:
315 return u.System_Double;
316 case Signature.ELEMENT_TYPE_STRING:
317 return u.System_String;
318 case Signature.ELEMENT_TYPE_SZARRAY:
319 return ReadFieldOrPropType(asm, br).MakeArrayType();
321 return ReadType(asm, br);
323 return u.System_Type;
325 return u.System_Object;
327 throw new BadImageFormatException();
331 private static CustomAttributeTypedArgument ReadFixedArg(Assembly asm, ByteReader br, Type type)
333 Universe u = asm.universe;
334 if (type == u.System_String)
336 return new CustomAttributeTypedArgument(type, br.ReadString());
338 else if (type == u.System_Boolean)
340 return new CustomAttributeTypedArgument(type, br.ReadByte() != 0);
342 else if (type == u.System_Char)
344 return new CustomAttributeTypedArgument(type, br.ReadChar());
346 else if (type == u.System_Single)
348 return new CustomAttributeTypedArgument(type, br.ReadSingle());
350 else if (type == u.System_Double)
352 return new CustomAttributeTypedArgument(type, br.ReadDouble());
354 else if (type == u.System_SByte)
356 return new CustomAttributeTypedArgument(type, br.ReadSByte());
358 else if (type == u.System_Int16)
360 return new CustomAttributeTypedArgument(type, br.ReadInt16());
362 else if (type == u.System_Int32)
364 return new CustomAttributeTypedArgument(type, br.ReadInt32());
366 else if (type == u.System_Int64)
368 return new CustomAttributeTypedArgument(type, br.ReadInt64());
370 else if (type == u.System_Byte)
372 return new CustomAttributeTypedArgument(type, br.ReadByte());
374 else if (type == u.System_UInt16)
376 return new CustomAttributeTypedArgument(type, br.ReadUInt16());
378 else if (type == u.System_UInt32)
380 return new CustomAttributeTypedArgument(type, br.ReadUInt32());
382 else if (type == u.System_UInt64)
384 return new CustomAttributeTypedArgument(type, br.ReadUInt64());
386 else if (type == u.System_Type)
388 return new CustomAttributeTypedArgument(type, ReadType(asm, br));
390 else if (type == u.System_Object)
392 return ReadFixedArg(asm, br, ReadFieldOrPropType(asm, br));
394 else if (type.IsArray)
396 int length = br.ReadInt32();
399 return new CustomAttributeTypedArgument(type, null);
401 Type elementType = type.GetElementType();
402 CustomAttributeTypedArgument[] array = new CustomAttributeTypedArgument[length];
403 for (int i = 0; i < length; i++)
405 array[i] = ReadFixedArg(asm, br, elementType);
407 return new CustomAttributeTypedArgument(type, array);
409 else if (type.IsEnum)
411 return new CustomAttributeTypedArgument(type, ReadFixedArg(asm, br, type.GetEnumUnderlyingTypeImpl()).Value);
415 throw new InvalidOperationException();
419 private static Type ReadType(Assembly asm, ByteReader br)
421 string typeName = br.ReadString();
422 if (typeName == null)
426 if (typeName.Length > 0 && typeName[typeName.Length - 1] == 0)
428 // there are broken compilers that emit an extra NUL character after the type name
429 typeName = typeName.Substring(0, typeName.Length - 1);
431 return TypeNameParser.Parse(typeName, true).GetType(asm.universe, asm, true, typeName, true, false);
434 private static IList<CustomAttributeTypedArgument> ReadConstructorArguments(Assembly asm, ByteReader br, ConstructorInfo constructor)
436 MethodSignature sig = constructor.MethodSignature;
437 int count = sig.GetParameterCount();
438 List<CustomAttributeTypedArgument> list = new List<CustomAttributeTypedArgument>(count);
439 for (int i = 0; i < count; i++)
441 list.Add(ReadFixedArg(asm, br, sig.GetParameterType(i)));
443 return list.AsReadOnly();
446 private static IList<CustomAttributeNamedArgument> ReadNamedArguments(Assembly asm, ByteReader br, int named, Type type)
448 List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>(named);
449 for (int i = 0; i < named; i++)
451 byte fieldOrProperty = br.ReadByte();
452 Type fieldOrPropertyType = ReadFieldOrPropType(asm, br);
453 string name = br.ReadString();
454 CustomAttributeTypedArgument value = ReadFixedArg(asm, br, fieldOrPropertyType);
456 switch (fieldOrProperty)
459 member = GetField(type, name, fieldOrPropertyType);
462 member = GetProperty(type, name, fieldOrPropertyType);
465 throw new BadImageFormatException();
467 list.Add(new CustomAttributeNamedArgument(member, value));
469 return list.AsReadOnly();
472 private static FieldInfo GetField(Type type, string name, Type fieldType)
475 for (; type != null && !type.__IsMissing; type = type.BaseType)
477 foreach (FieldInfo field in type.__GetDeclaredFields())
479 if (field.IsPublic && !field.IsStatic && field.Name == name)
485 // if the field is missing, we stick the missing field on the first missing base type
490 FieldSignature sig = FieldSignature.Create(fieldType, new CustomModifiers());
491 return type.FindField(name, sig)
492 ?? type.Module.universe.GetMissingFieldOrThrow(type, name, sig);
495 private static PropertyInfo GetProperty(Type type, string name, Type propertyType)
498 for (; type != null && !type.__IsMissing; type = type.BaseType)
500 foreach (PropertyInfo property in type.__GetDeclaredProperties())
502 if (property.IsPublic && !property.IsStatic && property.Name == name)
508 // if the property is missing, we stick the missing property on the first missing base type
513 return type.Module.universe.GetMissingPropertyOrThrow(type, name, PropertySignature.Create(CallingConventions.Standard | CallingConventions.HasThis, propertyType, null, new PackedCustomModifiers()));
516 [Obsolete("Use AttributeType property instead.")]
517 internal bool __TryReadTypeName(out string ns, out string name)
519 if (Constructor.DeclaringType.IsNested)
525 ns = Constructor.DeclaringType.__Namespace;
526 name = Constructor.DeclaringType.__Name;
530 public byte[] __GetBlob()
532 if (declSecurityBlob != null)
534 return (byte[])declSecurityBlob.Clone();
536 else if (customAttributeIndex == -1)
538 return __ToBuilder().GetBlob(module.Assembly);
542 return ((ModuleReader)module).GetBlobCopy(module.CustomAttribute.records[customAttributeIndex].Value);
550 return customAttributeIndex >= 0
551 ? module.CustomAttribute.records[customAttributeIndex].Parent
552 : declSecurityIndex >= 0
553 ? module.DeclSecurity.records[declSecurityIndex].Parent
559 public Type AttributeType
561 get { return Constructor.DeclaringType; }
564 public ConstructorInfo Constructor
568 if (lazyConstructor == null)
570 lazyConstructor = (ConstructorInfo)module.ResolveMethod(module.CustomAttribute.records[customAttributeIndex].Type);
572 return lazyConstructor;
576 public IList<CustomAttributeTypedArgument> ConstructorArguments
580 if (lazyConstructorArguments == null)
582 LazyParseArguments();
584 return lazyConstructorArguments;
588 public IList<CustomAttributeNamedArgument> NamedArguments
592 if (lazyNamedArguments == null)
594 if (customAttributeIndex >= 0)
596 // 1) Unresolved Custom Attribute
597 LazyParseArguments();
601 // 5) Unresolved declarative security
602 ByteReader br = new ByteReader(declSecurityBlob, 0, declSecurityBlob.Length);
603 // LAMESPEC the count of named arguments is a compressed integer (instead of UInt16 as NumNamed in custom attributes)
604 lazyNamedArguments = ReadNamedArguments(module.Assembly, br, br.ReadCompressedUInt(), Constructor.DeclaringType);
607 return lazyNamedArguments;
611 private void LazyParseArguments()
613 ByteReader br = module.GetBlob(module.CustomAttribute.records[customAttributeIndex].Value);
616 // it's legal to have an empty blob
617 lazyConstructorArguments = Empty<CustomAttributeTypedArgument>.Array;
618 lazyNamedArguments = Empty<CustomAttributeNamedArgument>.Array;
622 if (br.ReadUInt16() != 1)
624 throw new BadImageFormatException();
626 lazyConstructorArguments = ReadConstructorArguments(module.Assembly, br, Constructor);
627 lazyNamedArguments = ReadNamedArguments(module.Assembly, br, br.ReadUInt16(), Constructor.DeclaringType);
631 public CustomAttributeBuilder __ToBuilder()
633 ParameterInfo[] parameters = Constructor.GetParameters();
634 object[] args = new object[ConstructorArguments.Count];
635 for (int i = 0; i < args.Length; i++)
637 args[i] = RewrapArray(parameters[i].ParameterType, ConstructorArguments[i]);
639 List<PropertyInfo> namedProperties = new List<PropertyInfo>();
640 List<object> propertyValues = new List<object>();
641 List<FieldInfo> namedFields = new List<FieldInfo>();
642 List<object> fieldValues = new List<object>();
643 foreach (CustomAttributeNamedArgument named in NamedArguments)
645 PropertyInfo pi = named.MemberInfo as PropertyInfo;
648 namedProperties.Add(pi);
649 propertyValues.Add(RewrapArray(pi.PropertyType, named.TypedValue));
653 FieldInfo fi = (FieldInfo)named.MemberInfo;
655 fieldValues.Add(RewrapArray(fi.FieldType, named.TypedValue));
658 return new CustomAttributeBuilder(Constructor, args, namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray());
661 private static object RewrapArray(Type type, CustomAttributeTypedArgument arg)
663 IList<CustomAttributeTypedArgument> list = arg.Value as IList<CustomAttributeTypedArgument>;
666 Type elementType = arg.ArgumentType.GetElementType();
667 object[] arr = new object[list.Count];
668 for (int i = 0; i < arr.Length; i++)
670 arr[i] = RewrapArray(elementType, list[i]);
672 if (type == type.Module.universe.System_Object)
674 return CustomAttributeBuilder.__MakeTypedArgument(arg.ArgumentType, arr);
684 public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo member)
686 return __GetCustomAttributes(member, null, false);
689 public static IList<CustomAttributeData> GetCustomAttributes(Assembly assembly)
691 return assembly.GetCustomAttributesData(null);
694 public static IList<CustomAttributeData> GetCustomAttributes(Module module)
696 return __GetCustomAttributes(module, null, false);
699 public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo parameter)
701 return __GetCustomAttributes(parameter, null, false);
704 public static IList<CustomAttributeData> __GetCustomAttributes(Assembly assembly, Type attributeType, bool inherit)
706 return assembly.GetCustomAttributesData(attributeType);
709 public static IList<CustomAttributeData> __GetCustomAttributes(Module module, Type attributeType, bool inherit)
711 if (module.__IsMissing)
713 throw new MissingModuleException((MissingModule)module);
715 return GetCustomAttributesImpl(null, module, 0x00000001, attributeType) ?? EmptyList;
718 public static IList<CustomAttributeData> __GetCustomAttributes(ParameterInfo parameter, Type attributeType, bool inherit)
720 Module module = parameter.Module;
721 List<CustomAttributeData> list = null;
722 if (module.universe.ReturnPseudoCustomAttributes)
724 if (attributeType == null || attributeType.IsAssignableFrom(parameter.Module.universe.System_Runtime_InteropServices_MarshalAsAttribute))
727 if (parameter.__TryGetFieldMarshal(out spec))
731 list = new List<CustomAttributeData>();
733 list.Add(CustomAttributeData.CreateMarshalAsPseudoCustomAttribute(parameter.Module, spec));
737 ModuleBuilder mb = module as ModuleBuilder;
738 int token = parameter.MetadataToken;
739 if (mb != null && mb.IsSaved && ModuleBuilder.IsPseudoToken(token))
741 token = mb.ResolvePseudoToken(token);
743 return GetCustomAttributesImpl(list, module, token, attributeType) ?? EmptyList;
746 public static IList<CustomAttributeData> __GetCustomAttributes(MemberInfo member, Type attributeType, bool inherit)
750 // like .NET we we don't return custom attributes for unbaked members
751 throw new NotImplementedException();
753 if (!inherit || !IsInheritableAttribute(attributeType))
755 return GetCustomAttributesImpl(null, member, attributeType) ?? EmptyList;
757 List<CustomAttributeData> list = new List<CustomAttributeData>();
760 GetCustomAttributesImpl(list, member, attributeType);
761 Type type = member as Type;
764 type = type.BaseType;
772 MethodInfo method = member as MethodInfo;
775 MemberInfo prev = member;
776 method = method.GetBaseDefinition();
777 if (method == null || method == prev)
788 private static List<CustomAttributeData> GetCustomAttributesImpl(List<CustomAttributeData> list, MemberInfo member, Type attributeType)
790 if (member.Module.universe.ReturnPseudoCustomAttributes)
792 List<CustomAttributeData> pseudo = member.GetPseudoCustomAttributes(attributeType);
797 else if (pseudo != null)
799 list.AddRange(pseudo);
802 return GetCustomAttributesImpl(list, member.Module, member.GetCurrentToken(), attributeType);
805 internal static List<CustomAttributeData> GetCustomAttributesImpl(List<CustomAttributeData> list, Module module, int token, Type attributeType)
807 foreach (int i in module.CustomAttribute.Filter(token))
809 if (attributeType == null)
813 list = new List<CustomAttributeData>();
815 list.Add(new CustomAttributeData(module, i));
819 if (attributeType.IsAssignableFrom(module.ResolveMethod(module.CustomAttribute.records[i].Type).DeclaringType))
823 list = new List<CustomAttributeData>();
825 list.Add(new CustomAttributeData(module, i));
832 public static IList<CustomAttributeData> __GetCustomAttributes(Type type, Type interfaceType, Type attributeType, bool inherit)
834 Module module = type.Module;
835 foreach (int i in module.InterfaceImpl.Filter(type.MetadataToken))
837 if (module.ResolveType(module.InterfaceImpl.records[i].Interface, type) == interfaceType)
839 return GetCustomAttributesImpl(null, module, (InterfaceImplTable.Index << 24) | (i + 1), attributeType) ?? EmptyList;
845 public static IList<CustomAttributeData> __GetDeclarativeSecurity(Assembly assembly)
847 if (assembly.__IsMissing)
849 throw new MissingAssemblyException((MissingAssembly)assembly);
851 return assembly.ManifestModule.GetDeclarativeSecurity(0x20000001);
854 public static IList<CustomAttributeData> __GetDeclarativeSecurity(Type type)
856 if ((type.Attributes & TypeAttributes.HasSecurity) != 0)
858 return type.Module.GetDeclarativeSecurity(type.MetadataToken);
866 public static IList<CustomAttributeData> __GetDeclarativeSecurity(MethodBase method)
868 if ((method.Attributes & MethodAttributes.HasSecurity) != 0)
870 return method.Module.GetDeclarativeSecurity(method.MetadataToken);
878 private static bool IsInheritableAttribute(Type attribute)
880 Type attributeUsageAttribute = attribute.Module.universe.System_AttributeUsageAttribute;
881 IList<CustomAttributeData> attr = __GetCustomAttributes(attribute, attributeUsageAttribute, false);
884 foreach (CustomAttributeNamedArgument named in attr[0].NamedArguments)
886 if (named.MemberInfo.Name == "Inherited")
888 return (bool)named.TypedValue.Value;
895 internal static CustomAttributeData CreateDllImportPseudoCustomAttribute(Module module, ImplMapFlags flags, string entryPoint, string dllName, MethodImplAttributes attr)
897 Type type = module.universe.System_Runtime_InteropServices_DllImportAttribute;
898 ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_String);
899 List<CustomAttributeNamedArgument> list = new List<CustomAttributeNamedArgument>();
900 System.Runtime.InteropServices.CharSet charSet;
901 switch (flags & ImplMapFlags.CharSetMask)
903 case ImplMapFlags.CharSetAnsi:
904 charSet = System.Runtime.InteropServices.CharSet.Ansi;
906 case ImplMapFlags.CharSetUnicode:
907 charSet = System.Runtime.InteropServices.CharSet.Unicode;
909 case ImplMapFlags.CharSetAuto:
910 charSet = System.Runtime.InteropServices.CharSet.Auto;
912 case ImplMapFlags.CharSetNotSpec:
914 charSet = System.Runtime.InteropServices.CharSet.None;
917 System.Runtime.InteropServices.CallingConvention callingConvention;
918 switch (flags & ImplMapFlags.CallConvMask)
920 case ImplMapFlags.CallConvCdecl:
921 callingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl;
923 case ImplMapFlags.CallConvFastcall:
924 callingConvention = System.Runtime.InteropServices.CallingConvention.FastCall;
926 case ImplMapFlags.CallConvStdcall:
927 callingConvention = System.Runtime.InteropServices.CallingConvention.StdCall;
929 case ImplMapFlags.CallConvThiscall:
930 callingConvention = System.Runtime.InteropServices.CallingConvention.ThisCall;
932 case ImplMapFlags.CallConvWinapi:
933 callingConvention = System.Runtime.InteropServices.CallingConvention.Winapi;
936 callingConvention = 0;
939 AddNamedArgument(list, type, "EntryPoint", entryPoint);
940 AddNamedArgument(list, type, "CharSet", module.universe.System_Runtime_InteropServices_CharSet, (int)charSet);
941 AddNamedArgument(list, type, "ExactSpelling", (int)flags, (int)ImplMapFlags.NoMangle);
942 AddNamedArgument(list, type, "SetLastError", (int)flags, (int)ImplMapFlags.SupportsLastError);
943 AddNamedArgument(list, type, "PreserveSig", (int)attr, (int)MethodImplAttributes.PreserveSig);
944 AddNamedArgument(list, type, "CallingConvention", module.universe.System_Runtime_InteropServices_CallingConvention, (int)callingConvention);
945 AddNamedArgument(list, type, "BestFitMapping", (int)flags, (int)ImplMapFlags.BestFitOn);
946 AddNamedArgument(list, type, "ThrowOnUnmappableChar", (int)flags, (int)ImplMapFlags.CharMapErrorOn);
947 return new CustomAttributeData(module, constructor, new object[] { dllName }, list);
950 internal static CustomAttributeData CreateMarshalAsPseudoCustomAttribute(Module module, FieldMarshal fm)
952 Type typeofMarshalAs = module.universe.System_Runtime_InteropServices_MarshalAsAttribute;
953 Type typeofUnmanagedType = module.universe.System_Runtime_InteropServices_UnmanagedType;
954 Type typeofVarEnum = module.universe.System_Runtime_InteropServices_VarEnum;
955 Type typeofType = module.universe.System_Type;
956 List<CustomAttributeNamedArgument> named = new List<CustomAttributeNamedArgument>();
957 AddNamedArgument(named, typeofMarshalAs, "ArraySubType", typeofUnmanagedType, (int)(fm.ArraySubType ?? 0));
958 AddNamedArgument(named, typeofMarshalAs, "SizeParamIndex", module.universe.System_Int16, fm.SizeParamIndex ?? 0);
959 AddNamedArgument(named, typeofMarshalAs, "SizeConst", module.universe.System_Int32, fm.SizeConst ?? 0);
960 AddNamedArgument(named, typeofMarshalAs, "IidParameterIndex", module.universe.System_Int32, fm.IidParameterIndex ?? 0);
961 AddNamedArgument(named, typeofMarshalAs, "SafeArraySubType", typeofVarEnum, (int)(fm.SafeArraySubType ?? 0));
962 if (fm.SafeArrayUserDefinedSubType != null)
964 AddNamedArgument(named, typeofMarshalAs, "SafeArrayUserDefinedSubType", typeofType, fm.SafeArrayUserDefinedSubType);
966 if (fm.MarshalType != null)
968 AddNamedArgument(named, typeofMarshalAs, "MarshalType", module.universe.System_String, fm.MarshalType);
970 if (fm.MarshalTypeRef != null)
972 AddNamedArgument(named, typeofMarshalAs, "MarshalTypeRef", module.universe.System_Type, fm.MarshalTypeRef);
974 if (fm.MarshalCookie != null)
976 AddNamedArgument(named, typeofMarshalAs, "MarshalCookie", module.universe.System_String, fm.MarshalCookie);
978 ConstructorInfo constructor = typeofMarshalAs.GetPseudoCustomAttributeConstructor(typeofUnmanagedType);
979 return new CustomAttributeData(module, constructor, new object[] { (int)fm.UnmanagedType }, named);
982 private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, string value)
984 AddNamedArgument(list, type, fieldName, type.Module.universe.System_String, value);
987 private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, int flags, int flagMask)
989 AddNamedArgument(list, type, fieldName, type.Module.universe.System_Boolean, (flags & flagMask) != 0);
992 private static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type attributeType, string fieldName, Type valueType, object value)
994 // some fields are not available on the .NET Compact Framework version of DllImportAttribute/MarshalAsAttribute
995 FieldInfo field = attributeType.FindField(fieldName, FieldSignature.Create(valueType, new CustomModifiers()));
998 list.Add(new CustomAttributeNamedArgument(field, new CustomAttributeTypedArgument(valueType, value)));
1002 internal static CustomAttributeData CreateFieldOffsetPseudoCustomAttribute(Module module, int offset)
1004 Type type = module.universe.System_Runtime_InteropServices_FieldOffsetAttribute;
1005 ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_Int32);
1006 return new CustomAttributeData(module, constructor, new object[] { offset }, null);
1009 internal static CustomAttributeData CreatePreserveSigPseudoCustomAttribute(Module module)
1011 Type type = module.universe.System_Runtime_InteropServices_PreserveSigAttribute;
1012 ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor();
1013 return new CustomAttributeData(module, constructor, Empty<object>.Array, null);