IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
CustomAttributeData.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2009-2012 Jeroen Frijters
3
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.
7
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:
11
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.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Collections.Generic;
26using System.Text;
27
31
32namespace IKVM.Reflection
33{
34
35 internal sealed class CustomAttributeData
36 {
37
38 internal static readonly IList<CustomAttributeData> EmptyList = new List<CustomAttributeData>(0).AsReadOnly();
39
40 /*
41 * There are several states a CustomAttributeData object can be in:
42 *
43 * 1) Unresolved Custom Attribute
44 * - customAttributeIndex >= 0
45 * - declSecurityIndex == -1
46 * - declSecurityBlob == null
47 * - lazyConstructor = null
48 * - lazyConstructorArguments = null
49 * - lazyNamedArguments = null
50 *
51 * 2) Resolved Custom Attribute
52 * - customAttributeIndex >= 0
53 * - declSecurityIndex == -1
54 * - declSecurityBlob == null
55 * - lazyConstructor != null
56 * - lazyConstructorArguments != null
57 * - lazyNamedArguments != null
58 *
59 * 3) Pre-resolved Custom Attribute
60 * - customAttributeIndex = -1
61 * - declSecurityIndex == -1
62 * - declSecurityBlob == null
63 * - lazyConstructor != null
64 * - lazyConstructorArguments != null
65 * - lazyNamedArguments != null
66 *
67 * 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData()
68 * - customAttributeIndex = -1
69 * - declSecurityIndex == -1
70 * - declSecurityBlob == null
71 * - lazyConstructor != null
72 * - lazyConstructorArguments != null
73 * - lazyNamedArguments != null
74 *
75 * 5) Unresolved declarative security
76 * - customAttributeIndex = -1
77 * - declSecurityIndex >= 0
78 * - declSecurityBlob != null
79 * - lazyConstructor != null
80 * - lazyConstructorArguments != null
81 * - lazyNamedArguments == null
82 *
83 * 6) Resolved declarative security
84 * - customAttributeIndex = -1
85 * - declSecurityIndex >= 0
86 * - declSecurityBlob == null
87 * - lazyConstructor != null
88 * - lazyConstructorArguments != null
89 * - lazyNamedArguments != null
90 *
91 */
92
93 readonly Module module;
94 readonly int customAttributeIndex;
95 readonly int declSecurityIndex;
96 readonly byte[] declSecurityBlob;
97
98 ConstructorInfo lazyConstructor;
99 IList<CustomAttributeTypedArgument> lazyConstructorArguments;
100 IList<CustomAttributeNamedArgument> lazyNamedArguments;
101
107 internal CustomAttributeData(Module module, int index)
108 {
109 this.module = module ?? throw new ArgumentNullException(nameof(module));
110 this.customAttributeIndex = index;
111 this.declSecurityIndex = -1;
112 }
113
121 internal CustomAttributeData(Module module, ConstructorInfo constructor, object[] args, List<CustomAttributeNamedArgument> namedArguments) :
122 this(module, constructor, WrapConstructorArgs(args, constructor.MethodSignature), namedArguments)
123 {
124
125 }
126
127 static List<CustomAttributeTypedArgument> WrapConstructorArgs(object[] args, MethodSignature sig)
128 {
129 var list = new List<CustomAttributeTypedArgument>();
130 for (int i = 0; i < args.Length; i++)
131 list.Add(new CustomAttributeTypedArgument(sig.GetParameterType(i), args[i]));
132
133 return list;
134 }
135
136 // 4) Pseudo Custom Attribute, .NET 1.x declarative security or result of CustomAttributeBuilder.ToData()
137
146 internal CustomAttributeData(Module module, ConstructorInfo constructor, List<CustomAttributeTypedArgument> constructorArgs, List<CustomAttributeNamedArgument> namedArguments)
147 {
148 this.module = module ?? throw new ArgumentNullException(nameof(module));
149 this.customAttributeIndex = -1;
150 this.declSecurityIndex = -1;
151 this.lazyConstructor = constructor;
152
153 lazyConstructorArguments = constructorArgs.AsReadOnly();
154 if (namedArguments == null)
155 this.lazyNamedArguments = Array.Empty<CustomAttributeNamedArgument>();
156 else
157 this.lazyNamedArguments = namedArguments.AsReadOnly();
158 }
159
167 internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, ByteReader br)
168 {
169 this.module = asm.ManifestModule;
170 this.customAttributeIndex = -1;
171 this.declSecurityIndex = -1;
172 this.lazyConstructor = constructor;
173 if (br.Length == 0)
174 {
175 // it's legal to have an empty blob
176 lazyConstructorArguments = Array.Empty<CustomAttributeTypedArgument>();
177 lazyNamedArguments = Array.Empty<CustomAttributeNamedArgument>();
178 }
179 else
180 {
181 if (br.ReadUInt16() != 1)
182 throw new BadImageFormatException();
183
184 lazyConstructorArguments = ReadConstructorArguments(module, br, constructor);
185 lazyNamedArguments = ReadNamedArguments(module, br, br.ReadUInt16(), constructor.DeclaringType, true);
186 }
187 }
188
189 public override string ToString()
190 {
191 var sb = new StringBuilder();
192 sb.Append('[');
193 sb.Append(Constructor.DeclaringType.FullName);
194 sb.Append('(');
195
196 var sep = "";
197 var parameters = Constructor.GetParameters();
198 var args = ConstructorArguments;
199
200 for (int i = 0; i < parameters.Length; i++)
201 {
202 sb.Append(sep);
203 sep = ", ";
204 AppendValue(sb, parameters[i].ParameterType, args[i]);
205 }
206
207 foreach (var named in NamedArguments)
208 {
209 sb.Append(sep);
210 sep = ", ";
211 sb.Append(named.MemberInfo.Name);
212 sb.Append(" = ");
213 var fi = named.MemberInfo as FieldInfo;
214 var type = fi != null ? fi.FieldType : ((PropertyInfo)named.MemberInfo).PropertyType;
215 AppendValue(sb, type, named.TypedValue);
216 }
217 sb.Append(')');
218 sb.Append(']');
219
220 return sb.ToString();
221 }
222
223 static void AppendValue(StringBuilder sb, Type type, CustomAttributeTypedArgument arg)
224 {
225 if (arg.ArgumentType == arg.ArgumentType.Module.Universe.System_String)
226 {
227 sb.Append('"').Append(arg.Value).Append('"');
228 }
229 else if (arg.ArgumentType.IsArray)
230 {
231 var elementType = arg.ArgumentType.GetElementType();
232 string elementTypeName;
233 if (elementType.IsPrimitive
234 || elementType == type.Module.Universe.System_Object
235 || elementType == type.Module.Universe.System_String
236 || elementType == type.Module.Universe.System_Type)
237 {
238 elementTypeName = elementType.Name;
239 }
240 else
241 {
242 elementTypeName = elementType.FullName;
243 }
244 sb.Append("new ").Append(elementTypeName).Append("[").Append(((Array)arg.Value).Length).Append("] { ");
245 var sep = "";
246 foreach (var elem in (CustomAttributeTypedArgument[])arg.Value)
247 {
248 sb.Append(sep);
249 sep = ", ";
250 AppendValue(sb, elementType, elem);
251 }
252 sb.Append(" }");
253 }
254 else
255 {
256 if (arg.ArgumentType != type || (type.IsEnum && !arg.Value.Equals(0)))
257 {
258 sb.Append('(');
259 sb.Append(arg.ArgumentType.FullName);
260 sb.Append(')');
261 }
262
263 sb.Append(arg.Value);
264 }
265 }
266
267 internal static void ReadDeclarativeSecurity(Module module, int index, List<CustomAttributeData> list)
268 {
269 var asm = module.Assembly;
270 var action = module.DeclSecurityTable.records[index].Action;
271 var br = module.GetBlobReader(module.DeclSecurityTable.records[index].PermissionSet);
272 if (br.PeekByte() == '.')
273 {
274 br.ReadByte();
275 var count = br.ReadCompressedUInt();
276 for (int j = 0; j < count; j++)
277 {
278 var type = ReadType(module, br);
279 var constructor = type.GetPseudoCustomAttributeConstructor(module.Universe.System_Security_Permissions_SecurityAction);
280 // LAMESPEC there is an additional length here (probably of the named argument list)
281 var blob = br.ReadBytes(br.ReadCompressedUInt());
282 list.Add(new CustomAttributeData(asm, constructor, action, blob, index));
283 }
284 }
285 else
286 {
287 // .NET 1.x format (xml)
288 var buf = new char[br.Length / 2];
289 for (int i = 0; i < buf.Length; i++)
290 buf[i] = br.ReadChar();
291
292 var xml = new string(buf);
293 var ctor = module.Universe.System_Security_Permissions_PermissionSetAttribute.GetPseudoCustomAttributeConstructor(module.Universe.System_Security_Permissions_SecurityAction);
294 var args = new List<CustomAttributeNamedArgument>();
295 args.Add(new CustomAttributeNamedArgument(GetProperty(null, module.Universe.System_Security_Permissions_PermissionSetAttribute, "XML", module.Universe.System_String), new CustomAttributeTypedArgument(module.Universe.System_String, xml)));
296 list.Add(new CustomAttributeData(asm.ManifestModule, ctor, new object[] { action }, args));
297 }
298 }
299
308 internal CustomAttributeData(Assembly asm, ConstructorInfo constructor, int securityAction, byte[] blob, int index)
309 {
310 this.module = asm.ManifestModule;
311 this.customAttributeIndex = -1;
312 this.declSecurityIndex = index;
313 this.lazyConstructor = constructor;
314
315 var list = new List<CustomAttributeTypedArgument>();
316 list.Add(new CustomAttributeTypedArgument(constructor.Module.Universe.System_Security_Permissions_SecurityAction, securityAction));
317 this.lazyConstructorArguments = list.AsReadOnly();
318 this.declSecurityBlob = blob;
319 }
320
321 static Type ReadFieldOrPropType(Module context, ByteReader br)
322 {
323 return br.ReadByte() switch
324 {
325 Signature.ELEMENT_TYPE_BOOLEAN => context.Universe.System_Boolean,
326 Signature.ELEMENT_TYPE_CHAR => context.Universe.System_Char,
327 Signature.ELEMENT_TYPE_I1 => context.Universe.System_SByte,
328 Signature.ELEMENT_TYPE_U1 => context.Universe.System_Byte,
329 Signature.ELEMENT_TYPE_I2 => context.Universe.System_Int16,
330 Signature.ELEMENT_TYPE_U2 => context.Universe.System_UInt16,
331 Signature.ELEMENT_TYPE_I4 => context.Universe.System_Int32,
332 Signature.ELEMENT_TYPE_U4 => context.Universe.System_UInt32,
333 Signature.ELEMENT_TYPE_I8 => context.Universe.System_Int64,
334 Signature.ELEMENT_TYPE_U8 => context.Universe.System_UInt64,
335 Signature.ELEMENT_TYPE_R4 => context.Universe.System_Single,
336 Signature.ELEMENT_TYPE_R8 => context.Universe.System_Double,
337 Signature.ELEMENT_TYPE_STRING => context.Universe.System_String,
338 Signature.ELEMENT_TYPE_SZARRAY => ReadFieldOrPropType(context, br).MakeArrayType(),
339 0x55 => ReadType(context, br),
340 0x50 => context.Universe.System_Type,
341 0x51 => context.Universe.System_Object,
342 _ => throw new BadImageFormatException(),
343 };
344 }
345
346 static CustomAttributeTypedArgument ReadFixedArg(Module context, ByteReader br, Type type)
347 {
348 var u = context.Universe;
349 if (type == u.System_String)
350 {
351 return new CustomAttributeTypedArgument(type, br.ReadString());
352 }
353 else if (type == u.System_Boolean)
354 {
355 return new CustomAttributeTypedArgument(type, br.ReadByte() != 0);
356 }
357 else if (type == u.System_Char)
358 {
359 return new CustomAttributeTypedArgument(type, br.ReadChar());
360 }
361 else if (type == u.System_Single)
362 {
363 return new CustomAttributeTypedArgument(type, br.ReadSingle());
364 }
365 else if (type == u.System_Double)
366 {
367 return new CustomAttributeTypedArgument(type, br.ReadDouble());
368 }
369 else if (type == u.System_SByte)
370 {
371 return new CustomAttributeTypedArgument(type, br.ReadSByte());
372 }
373 else if (type == u.System_Int16)
374 {
375 return new CustomAttributeTypedArgument(type, br.ReadInt16());
376 }
377 else if (type == u.System_Int32)
378 {
379 return new CustomAttributeTypedArgument(type, br.ReadInt32());
380 }
381 else if (type == u.System_Int64)
382 {
383 return new CustomAttributeTypedArgument(type, br.ReadInt64());
384 }
385 else if (type == u.System_Byte)
386 {
387 return new CustomAttributeTypedArgument(type, br.ReadByte());
388 }
389 else if (type == u.System_UInt16)
390 {
391 return new CustomAttributeTypedArgument(type, br.ReadUInt16());
392 }
393 else if (type == u.System_UInt32)
394 {
395 return new CustomAttributeTypedArgument(type, br.ReadUInt32());
396 }
397 else if (type == u.System_UInt64)
398 {
399 return new CustomAttributeTypedArgument(type, br.ReadUInt64());
400 }
401 else if (type == u.System_Type)
402 {
403 return new CustomAttributeTypedArgument(type, ReadType(context, br));
404 }
405 else if (type == u.System_Object)
406 {
407 return ReadFixedArg(context, br, ReadFieldOrPropType(context, br));
408 }
409 else if (type.IsArray)
410 {
411 var length = br.ReadInt32();
412 if (length == -1)
413 return new CustomAttributeTypedArgument(type, null);
414
415 var elementType = type.GetElementType();
416 var array = new CustomAttributeTypedArgument[length];
417 for (int i = 0; i < length; i++)
418 array[i] = ReadFixedArg(context, br, elementType);
419
420 return new CustomAttributeTypedArgument(type, array);
421 }
422 else if (type.IsEnum)
423 {
424 return new CustomAttributeTypedArgument(type, ReadFixedArg(context, br, type.GetEnumUnderlyingTypeImpl()).Value);
425 }
426 else
427 {
428 throw new InvalidOperationException();
429 }
430 }
431
432 static Type ReadType(Module context, ByteReader br)
433 {
434 var typeName = br.ReadString();
435 if (typeName == null)
436 return null;
437
438 // there are broken compilers that emit an extra NUL character after the type name
439 if (typeName.Length > 0 && typeName[typeName.Length - 1] == 0)
440 typeName = typeName.Substring(0, typeName.Length - 1);
441
442 return TypeNameParser.Parse(typeName, true).GetType(context.Universe, context, true, typeName, true, false);
443 }
444
445 static IList<CustomAttributeTypedArgument> ReadConstructorArguments(Module context, ByteReader br, ConstructorInfo constructor)
446 {
447 var sig = constructor.MethodSignature;
448 var count = sig.GetParameterCount();
449 var list = new List<CustomAttributeTypedArgument>(count);
450 for (int i = 0; i < count; i++)
451 list.Add(ReadFixedArg(context, br, sig.GetParameterType(i)));
452
453 return list.AsReadOnly();
454 }
455
456 static IList<CustomAttributeNamedArgument> ReadNamedArguments(Module context, ByteReader br, int named, Type type, bool required)
457 {
458 var list = new List<CustomAttributeNamedArgument>(named);
459 for (int i = 0; i < named; i++)
460 {
461 var fieldOrProperty = br.ReadByte();
462 var fieldOrPropertyType = ReadFieldOrPropType(context, br);
463 if (fieldOrPropertyType.__IsMissing && !required)
464 return null;
465
466 var name = br.ReadString();
467 var value = ReadFixedArg(context, br, fieldOrPropertyType);
468 var member = fieldOrProperty switch
469 {
470 0x53 => (MemberInfo)GetField(context, type, name, fieldOrPropertyType),
471 0x54 => (MemberInfo)GetProperty(context, type, name, fieldOrPropertyType),
472 _ => throw new BadImageFormatException(),
473 };
474
475 list.Add(new CustomAttributeNamedArgument(member, value));
476 }
477
478 return list.AsReadOnly();
479 }
480
481 static FieldInfo GetField(Module context, Type type, string name, Type fieldType)
482 {
483 var org = type;
484 for (; type != null && !type.__IsMissing; type = type.BaseType)
485 foreach (FieldInfo field in type.__GetDeclaredFields())
486 if (field.IsPublic && !field.IsStatic && field.Name == name)
487 return field;
488
489 // if the field is missing, we stick the missing field on the first missing base type
490 if (type == null)
491 type = org;
492
493 var sig = FieldSignature.Create(fieldType, new CustomModifiers());
494 return type.FindField(name, sig) ?? type.Module.Universe.GetMissingFieldOrThrow(context, type, name, sig);
495 }
496
497 static PropertyInfo GetProperty(Module context, Type type, string name, Type propertyType)
498 {
499 var org = type;
500 for (; type != null && !type.__IsMissing; type = type.BaseType)
501 foreach (PropertyInfo property in type.__GetDeclaredProperties())
502 if (property.IsPublic && !property.IsStatic && property.Name == name)
503 return property;
504
505 // if the property is missing, we stick the missing property on the first missing base type
506 if (type == null)
507 type = org;
508
509 return type.Module.Universe.GetMissingPropertyOrThrow(context, type, name, PropertySignature.Create(CallingConventions.Standard | CallingConventions.HasThis, propertyType, null, new PackedCustomModifiers()));
510 }
511
512 [Obsolete("Use AttributeType property instead.")]
513 internal bool __TryReadTypeName(out string ns, out string name)
514 {
515 if (Constructor.DeclaringType.IsNested)
516 {
517 ns = null;
518 name = null;
519 return false;
520 }
521
522 var typeName = AttributeType.TypeName;
523 ns = typeName.Namespace;
524 name = typeName.Name;
525 return true;
526 }
527
528 public byte[] __GetBlob()
529 {
530 if (declSecurityBlob != null)
531 return (byte[])declSecurityBlob.Clone();
532 else if (customAttributeIndex == -1)
533 return __ToBuilder().GetBlob(module.Assembly);
534 else
535 return ((ModuleReader)module).GetBlobCopy(module.CustomAttributeTable.records[customAttributeIndex].Value);
536 }
537
538 public int __Parent
539 {
540 get
541 {
542 return customAttributeIndex >= 0
543 ? module.CustomAttributeTable.records[customAttributeIndex].Parent
544 : declSecurityIndex >= 0
545 ? module.DeclSecurityTable.records[declSecurityIndex].Parent
546 : 0;
547 }
548 }
549
550 public Type AttributeType
551 {
552 get { return Constructor.DeclaringType; }
553 }
554
555 public ConstructorInfo Constructor
556 {
557 get
558 {
559 if (lazyConstructor == null)
560 lazyConstructor = (ConstructorInfo)module.ResolveMethod(module.CustomAttributeTable.records[customAttributeIndex].Constructor);
561
562 return lazyConstructor;
563 }
564 }
565
566 public IList<CustomAttributeTypedArgument> ConstructorArguments
567 {
568 get
569 {
570 if (lazyConstructorArguments == null)
571 LazyParseArguments(false);
572
573 return lazyConstructorArguments;
574 }
575 }
576
577 public IList<CustomAttributeNamedArgument> NamedArguments
578 {
579 get
580 {
581 if (lazyNamedArguments == null)
582 {
583 if (customAttributeIndex >= 0)
584 {
585 // 1) Unresolved Custom Attribute
586 LazyParseArguments(true);
587 }
588 else
589 {
590 // 5) Unresolved declarative security
591 ByteReader br = new ByteReader(declSecurityBlob, 0, declSecurityBlob.Length);
592 // LAMESPEC the count of named arguments is a compressed integer (instead of UInt16 as NumNamed in custom attributes)
593 lazyNamedArguments = ReadNamedArguments(module, br, br.ReadCompressedUInt(), Constructor.DeclaringType, true);
594 }
595 }
596
597 return lazyNamedArguments;
598 }
599 }
600
601 void LazyParseArguments(bool requireNameArguments)
602 {
603 var br = module.GetBlobReader(module.CustomAttributeTable.records[customAttributeIndex].Value);
604 if (br.Length == 0)
605 {
606 // it's legal to have an empty blob
607 lazyConstructorArguments = Array.Empty<CustomAttributeTypedArgument>();
608 lazyNamedArguments = Array.Empty<CustomAttributeNamedArgument>();
609 }
610 else
611 {
612 if (br.ReadUInt16() != 1)
613 throw new BadImageFormatException();
614
615 lazyConstructorArguments = ReadConstructorArguments(module, br, Constructor);
616 lazyNamedArguments = ReadNamedArguments(module, br, br.ReadUInt16(), Constructor.DeclaringType, requireNameArguments);
617 }
618 }
619
620 public CustomAttributeBuilder __ToBuilder()
621 {
622 var parameters = Constructor.GetParameters();
623 var args = new object[ConstructorArguments.Count];
624 for (int i = 0; i < args.Length; i++)
625 args[i] = RewrapArray(parameters[i].ParameterType, ConstructorArguments[i]);
626
627 var namedProperties = new List<PropertyInfo>();
628 var propertyValues = new List<object>();
629 var namedFields = new List<FieldInfo>();
630 var fieldValues = new List<object>();
631
632 foreach (var named in NamedArguments)
633 {
634 var pi = named.MemberInfo as PropertyInfo;
635 if (pi != null)
636 {
637 namedProperties.Add(pi);
638 propertyValues.Add(RewrapArray(pi.PropertyType, named.TypedValue));
639 }
640 else
641 {
642 var fi = (FieldInfo)named.MemberInfo;
643 namedFields.Add(fi);
644 fieldValues.Add(RewrapArray(fi.FieldType, named.TypedValue));
645 }
646 }
647
648 return new CustomAttributeBuilder(Constructor, args, namedProperties.ToArray(), propertyValues.ToArray(), namedFields.ToArray(), fieldValues.ToArray());
649 }
650
651 static object RewrapArray(Type type, CustomAttributeTypedArgument arg)
652 {
653 var list = arg.Value as IList<CustomAttributeTypedArgument>;
654 if (list != null)
655 {
656 var elementType = arg.ArgumentType.GetElementType();
657 var arr = new object[list.Count];
658 for (int i = 0; i < arr.Length; i++)
659 arr[i] = RewrapArray(elementType, list[i]);
660
661 if (type == type.Module.Universe.System_Object)
662 return CustomAttributeBuilder.__MakeTypedArgument(arg.ArgumentType, arr);
663
664 return arr;
665 }
666 else
667 {
668 return arg.Value;
669 }
670 }
671
672 public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo member)
673 {
674 return __GetCustomAttributes(member, null, false);
675 }
676
677 public static IList<CustomAttributeData> GetCustomAttributes(Assembly assembly)
678 {
679 return assembly.GetCustomAttributesData(null);
680 }
681
682 public static IList<CustomAttributeData> GetCustomAttributes(Module module)
683 {
684 return __GetCustomAttributes(module, null, false);
685 }
686
687 public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo parameter)
688 {
689 return __GetCustomAttributes(parameter, null, false);
690 }
691
692 public static IList<CustomAttributeData> __GetCustomAttributes(Assembly assembly, Type attributeType, bool inherit)
693 {
694 return assembly.GetCustomAttributesData(attributeType);
695 }
696
697 public static IList<CustomAttributeData> __GetCustomAttributes(Module module, Type attributeType, bool inherit)
698 {
699 if (module.__IsMissing)
700 throw new MissingModuleException((MissingModule)module);
701
702 return GetCustomAttributesImpl(null, module, 0x00000001, attributeType) ?? EmptyList;
703 }
704
705 public static IList<CustomAttributeData> __GetCustomAttributes(ParameterInfo parameter, Type attributeType, bool inherit)
706 {
707 var module = parameter.Module;
708 List<CustomAttributeData> list = null;
709 if (module.Universe.ReturnPseudoCustomAttributes)
710 {
711 if (attributeType == null || attributeType.IsAssignableFrom(parameter.Module.Universe.System_Runtime_InteropServices_MarshalAsAttribute))
712 {
713 if (parameter.__TryGetFieldMarshal(out var spec))
714 {
715 list ??= new List<CustomAttributeData>();
716 list.Add(CustomAttributeData.CreateMarshalAsPseudoCustomAttribute(parameter.Module, spec));
717 }
718 }
719 }
720
721 var token = parameter.MetadataToken;
722 if (module is ModuleBuilder mb && mb.IsSaved && ModuleBuilder.IsPseudoToken(token))
723 token = mb.ResolvePseudoToken(token);
724
725 return GetCustomAttributesImpl(list, module, token, attributeType) ?? EmptyList;
726 }
727
728 public static IList<CustomAttributeData> __GetCustomAttributes(MemberInfo member, Type attributeType, bool inherit)
729 {
730 // like .NET we we don't return custom attributes for unbaked members
731 if (!member.IsBaked)
732 throw new NotImplementedException();
733
734 if (!inherit || !IsInheritableAttribute(attributeType))
735 return GetCustomAttributesImpl(null, member, attributeType) ?? EmptyList;
736
737 var list = new List<CustomAttributeData>();
738 for (; ; )
739 {
740 GetCustomAttributesImpl(list, member, attributeType);
741
742 var type = member as Type;
743 if (type != null)
744 {
745 type = type.BaseType;
746 if (type == null)
747 return list;
748
749 member = type;
750 continue;
751 }
752
753 var method = member as MethodInfo;
754 if (method != null)
755 {
756 var prev = member;
757 method = method.GetBaseDefinition();
758 if (method == null || method == prev)
759 return list;
760
761 member = method;
762 continue;
763 }
764
765 return list;
766 }
767 }
768
769 static List<CustomAttributeData> GetCustomAttributesImpl(List<CustomAttributeData> list, MemberInfo member, Type attributeType)
770 {
771 if (member.Module.Universe.ReturnPseudoCustomAttributes)
772 {
773 var pseudo = member.GetPseudoCustomAttributes(attributeType);
774 if (list == null)
775 list = pseudo;
776 else if (pseudo != null)
777 list.AddRange(pseudo);
778 }
779
780 return GetCustomAttributesImpl(list, member.Module, member.GetCurrentToken(), attributeType);
781 }
782
783 internal static List<CustomAttributeData> GetCustomAttributesImpl(List<CustomAttributeData> list, Module module, int token, Type attributeType)
784 {
785 foreach (var i in module.CustomAttributeTable.Filter(token))
786 {
787 if (attributeType == null)
788 {
789 list ??= new List<CustomAttributeData>();
790 list.Add(new CustomAttributeData(module, i));
791 }
792 else
793 {
794 if (attributeType.IsAssignableFrom(module.ResolveMethod(module.CustomAttributeTable.records[i].Constructor).DeclaringType))
795 {
796 list ??= new List<CustomAttributeData>();
797 list.Add(new CustomAttributeData(module, i));
798 }
799 }
800 }
801
802 return list;
803 }
804
805 public static IList<CustomAttributeData> __GetCustomAttributes(Type type, Type interfaceType, Type attributeType, bool inherit)
806 {
807 var module = type.Module;
808 foreach (int i in module.InterfaceImplTable.Filter(type.MetadataToken))
809 if (module.ResolveType(module.InterfaceImplTable.records[i].Interface, type) == interfaceType)
810 return GetCustomAttributesImpl(null, module, (InterfaceImplTable.Index << 24) | (i + 1), attributeType) ?? EmptyList;
811
812 return EmptyList;
813 }
814
815 public static IList<CustomAttributeData> __GetDeclarativeSecurity(Assembly assembly)
816 {
817 if (assembly.__IsMissing)
818 throw new MissingAssemblyException((MissingAssembly)assembly);
819
820 return assembly.ManifestModule.GetDeclarativeSecurity(0x20000001);
821 }
822
823 public static IList<CustomAttributeData> __GetDeclarativeSecurity(Type type)
824 {
825 if ((type.Attributes & TypeAttributes.HasSecurity) != 0)
826 return type.Module.GetDeclarativeSecurity(type.MetadataToken);
827 else
828 return EmptyList;
829 }
830
831 public static IList<CustomAttributeData> __GetDeclarativeSecurity(MethodBase method)
832 {
833 if ((method.Attributes & MethodAttributes.HasSecurity) != 0)
834 return method.Module.GetDeclarativeSecurity(method.MetadataToken);
835 else
836 return EmptyList;
837 }
838
839 private static bool IsInheritableAttribute(Type attribute)
840 {
841 var attributeUsageAttribute = attribute.Module.Universe.System_AttributeUsageAttribute;
842 var attr = __GetCustomAttributes(attribute, attributeUsageAttribute, false);
843 if (attr.Count != 0)
844 foreach (CustomAttributeNamedArgument named in attr[0].NamedArguments)
845 if (named.MemberInfo.Name == "Inherited")
846 return (bool)named.TypedValue.Value;
847
848 return true;
849 }
850
851 internal static CustomAttributeData CreateDllImportPseudoCustomAttribute(Module module, ImplMapFlags flags, string entryPoint, string dllName, MethodImplAttributes attr)
852 {
853
854 var charSet = (flags & ImplMapFlags.CharSetMask) switch
855 {
856 ImplMapFlags.CharSetAnsi => System.Runtime.InteropServices.CharSet.Ansi,
857 ImplMapFlags.CharSetUnicode => System.Runtime.InteropServices.CharSet.Unicode,
858 ImplMapFlags.CharSetAuto => System.Runtime.InteropServices.CharSet.Auto,
859 _ => System.Runtime.InteropServices.CharSet.None,
860 };
861
862 var callingConvention = (flags & ImplMapFlags.CallConvMask) switch
863 {
864 ImplMapFlags.CallConvCdecl => System.Runtime.InteropServices.CallingConvention.Cdecl,
865 ImplMapFlags.CallConvFastcall => System.Runtime.InteropServices.CallingConvention.FastCall,
866 ImplMapFlags.CallConvStdcall => System.Runtime.InteropServices.CallingConvention.StdCall,
867 ImplMapFlags.CallConvThiscall => System.Runtime.InteropServices.CallingConvention.ThisCall,
868 ImplMapFlags.CallConvWinapi => System.Runtime.InteropServices.CallingConvention.Winapi,
869 _ => (System.Runtime.InteropServices.CallingConvention)0,
870 };
871
872 var list = new List<CustomAttributeNamedArgument>();
873 var type = module.Universe.System_Runtime_InteropServices_DllImportAttribute;
874 var constructor = type.GetPseudoCustomAttributeConstructor(module.Universe.System_String);
875 AddNamedArgument(list, type, "EntryPoint", entryPoint);
876 AddNamedArgument(list, type, "CharSet", module.Universe.System_Runtime_InteropServices_CharSet, (int)charSet);
877 AddNamedArgument(list, type, "ExactSpelling", (int)flags, (int)ImplMapFlags.NoMangle);
878 AddNamedArgument(list, type, "SetLastError", (int)flags, (int)ImplMapFlags.SupportsLastError);
879 AddNamedArgument(list, type, "PreserveSig", (int)attr, (int)MethodImplAttributes.PreserveSig);
880 AddNamedArgument(list, type, "CallingConvention", module.Universe.System_Runtime_InteropServices_CallingConvention, (int)callingConvention);
881 AddNamedArgument(list, type, "BestFitMapping", (int)flags, (int)ImplMapFlags.BestFitOn);
882 AddNamedArgument(list, type, "ThrowOnUnmappableChar", (int)flags, (int)ImplMapFlags.CharMapErrorOn);
883 return new CustomAttributeData(module, constructor, new object[] { dllName }, list);
884 }
885
886 internal static CustomAttributeData CreateMarshalAsPseudoCustomAttribute(Module module, FieldMarshal fm)
887 {
888 var typeofMarshalAs = module.Universe.System_Runtime_InteropServices_MarshalAsAttribute;
889 var typeofUnmanagedType = module.Universe.System_Runtime_InteropServices_UnmanagedType;
890 var typeofVarEnum = module.Universe.System_Runtime_InteropServices_VarEnum;
891 var typeofType = module.Universe.System_Type;
892 var named = new List<CustomAttributeNamedArgument>();
893 AddNamedArgument(named, typeofMarshalAs, "ArraySubType", typeofUnmanagedType, (int)(fm.ArraySubType ?? 0));
894 AddNamedArgument(named, typeofMarshalAs, "SizeParamIndex", module.Universe.System_Int16, fm.SizeParamIndex ?? 0);
895 AddNamedArgument(named, typeofMarshalAs, "SizeConst", module.Universe.System_Int32, fm.SizeConst ?? 0);
896 AddNamedArgument(named, typeofMarshalAs, "IidParameterIndex", module.Universe.System_Int32, fm.IidParameterIndex ?? 0);
897 AddNamedArgument(named, typeofMarshalAs, "SafeArraySubType", typeofVarEnum, (int)(fm.SafeArraySubType ?? 0));
898 if (fm.SafeArrayUserDefinedSubType != null)
899 AddNamedArgument(named, typeofMarshalAs, "SafeArrayUserDefinedSubType", typeofType, fm.SafeArrayUserDefinedSubType);
900 if (fm.MarshalType != null)
901 AddNamedArgument(named, typeofMarshalAs, "MarshalType", module.Universe.System_String, fm.MarshalType);
902 if (fm.MarshalTypeRef != null)
903 AddNamedArgument(named, typeofMarshalAs, "MarshalTypeRef", module.Universe.System_Type, fm.MarshalTypeRef);
904 if (fm.MarshalCookie != null)
905 AddNamedArgument(named, typeofMarshalAs, "MarshalCookie", module.Universe.System_String, fm.MarshalCookie);
906
907 var constructor = typeofMarshalAs.GetPseudoCustomAttributeConstructor(typeofUnmanagedType);
908 return new CustomAttributeData(module, constructor, new object[] { (int)fm.UnmanagedType }, named);
909 }
910
911 static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, string value)
912 {
913 AddNamedArgument(list, type, fieldName, type.Module.Universe.System_String, value);
914 }
915
916 static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type type, string fieldName, int flags, int flagMask)
917 {
918 AddNamedArgument(list, type, fieldName, type.Module.Universe.System_Boolean, (flags & flagMask) != 0);
919 }
920
921 static void AddNamedArgument(List<CustomAttributeNamedArgument> list, Type attributeType, string fieldName, Type valueType, object value)
922 {
923 // some fields are not available on the .NET Compact Framework version of DllImportAttribute/MarshalAsAttribute
924 var field = attributeType.FindField(fieldName, FieldSignature.Create(valueType, new CustomModifiers()));
925 if (field != null)
926 list.Add(new CustomAttributeNamedArgument(field, new CustomAttributeTypedArgument(valueType, value)));
927 }
928
929 internal static CustomAttributeData CreateFieldOffsetPseudoCustomAttribute(Module module, int offset)
930 {
931 var type = module.Universe.System_Runtime_InteropServices_FieldOffsetAttribute;
932 var constructor = type.GetPseudoCustomAttributeConstructor(module.Universe.System_Int32);
933 return new CustomAttributeData(module, constructor, new object[] { offset }, null);
934 }
935
936 internal static CustomAttributeData CreatePreserveSigPseudoCustomAttribute(Module module)
937 {
938 var type = module.Universe.System_Runtime_InteropServices_PreserveSigAttribute;
939 var constructor = type.GetPseudoCustomAttributeConstructor();
940 return new CustomAttributeData(module, constructor, Array.Empty<object>(), null);
941 }
942
943 }
944
945}
IKVM.Reflection.Module Module
IKVM.Reflection.Type Type
IKVM.Reflection.Assembly Assembly
IKVM.Reflection.ConstructorInfo ConstructorInfo
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.MemberInfo MemberInfo
IKVM.Reflection.PropertyInfo PropertyInfo
IKVM.Reflection.MethodInfo MethodInfo
IKVM.Reflection.ParameterInfo ParameterInfo
IKVM.Reflection.MethodBase MethodBase
Represents a method signature from IL metadadata.
override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)