[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / corlib / System / MonoCustomAttrs.cs
blob7bb4716dad84c990745fce414878ca2332ab3360
1 //
2 // MonoCustomAttrs.cs: Hooks into the runtime to get custom attributes for reflection handles
3 //
4 // Authors:
5 // Paolo Molaro (lupus@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
8 //
9 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Copyright (C) 2013 Xamarin, Inc (http://www.xamarin.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System;
34 using System.Reflection;
35 using System.Collections;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.InteropServices;
38 #if !FULL_AOT_RUNTIME
39 using System.Reflection.Emit;
40 #endif
42 using System.Collections.Generic;
44 namespace System
46 static class MonoCustomAttrs
48 static Assembly corlib;
49 [ThreadStatic]
50 static Dictionary<Type, AttributeUsageAttribute> usage_cache;
52 /* Treat as user types all corlib types extending System.Type that are not RuntimeType and TypeBuilder */
53 static bool IsUserCattrProvider (object obj)
55 Type type = obj as Type;
56 #if !FULL_AOT_RUNTIME
57 if ((type is RuntimeType) || (RuntimeFeature.IsDynamicCodeSupported && type is TypeBuilder))
58 #else
59 if (type is RuntimeType)
60 #endif
61 return false;
62 if ((obj is Type))
63 return true;
64 if (corlib == null)
65 corlib = typeof (int).Assembly;
66 return obj.GetType ().Assembly != corlib;
69 [MethodImplAttribute (MethodImplOptions.InternalCall)]
70 internal static extern Attribute[] GetCustomAttributesInternal (ICustomAttributeProvider obj, Type attributeType, bool pseudoAttrs);
72 internal static object[] GetPseudoCustomAttributes (ICustomAttributeProvider obj, Type attributeType) {
73 object[] pseudoAttrs = null;
74 /* FIXME: Add other types */
75 if (obj is RuntimeMethodInfo monoMethod)
76 pseudoAttrs = monoMethod.GetPseudoCustomAttributes ();
77 else if (obj is RuntimeFieldInfo fieldInfo)
78 pseudoAttrs = fieldInfo.GetPseudoCustomAttributes ();
79 else if (obj is RuntimeParameterInfo monoParamInfo)
80 pseudoAttrs = monoParamInfo.GetPseudoCustomAttributes ();
81 else if (obj is Type t)
82 pseudoAttrs = GetPseudoCustomAttributes (t);
84 if ((attributeType != null) && (pseudoAttrs != null)) {
85 for (int i = 0; i < pseudoAttrs.Length; ++i)
86 if (attributeType.IsAssignableFrom (pseudoAttrs [i].GetType ()))
87 if (pseudoAttrs.Length == 1)
88 return pseudoAttrs;
89 else
90 return new object [] { pseudoAttrs [i] };
91 return Array.Empty<object> ();
94 return pseudoAttrs;
97 static object[] GetPseudoCustomAttributes (Type type)
99 int count = 0;
100 var Attributes = type.Attributes;
102 /* IsSerializable returns true for delegates/enums as well */
103 if ((Attributes & TypeAttributes.Serializable) != 0)
104 count ++;
105 if ((Attributes & TypeAttributes.Import) != 0)
106 count ++;
108 if (count == 0)
109 return null;
110 object[] attrs = new object [count];
111 count = 0;
113 if ((Attributes & TypeAttributes.Serializable) != 0)
114 attrs [count ++] = new SerializableAttribute ();
115 if ((Attributes & TypeAttributes.Import) != 0)
116 attrs [count ++] = new ComImportAttribute ();
118 return attrs;
121 internal static object[] GetCustomAttributesBase (ICustomAttributeProvider obj, Type attributeType, bool inheritedOnly)
123 object[] attrs;
125 if (IsUserCattrProvider (obj))
126 attrs = obj.GetCustomAttributes (attributeType, true);
127 else
128 attrs = GetCustomAttributesInternal (obj, attributeType, false);
131 // All pseudo custom attributes are Inherited = false hence we can avoid
132 // building attributes array which would be discarded by inherited checks
134 if (!inheritedOnly) {
135 object[] pseudoAttrs = GetPseudoCustomAttributes (obj, attributeType);
136 if (pseudoAttrs != null) {
137 object[] res = new Attribute [attrs.Length + pseudoAttrs.Length];
138 System.Array.Copy (attrs, res, attrs.Length);
139 System.Array.Copy (pseudoAttrs, 0, res, attrs.Length, pseudoAttrs.Length);
140 return res;
144 return attrs;
147 internal static object[] GetCustomAttributes (ICustomAttributeProvider obj, Type attributeType, bool inherit)
149 if (obj == null)
150 throw new ArgumentNullException (nameof (obj));
151 if (attributeType == null)
152 throw new ArgumentNullException (nameof (attributeType));
154 if (attributeType == typeof (MonoCustomAttrs))
155 attributeType = null;
157 object[] r;
158 object[] res = GetCustomAttributesBase (obj, attributeType, false);
159 // shortcut
160 if (!inherit && res.Length == 1) {
161 if (res [0] == null)
162 throw new CustomAttributeFormatException ("Invalid custom attribute format");
164 if (attributeType != null) {
165 if (attributeType.IsAssignableFrom (res[0].GetType ())) {
166 r = (object[]) Array.CreateInstance (attributeType, 1);
167 r[0] = res[0];
168 } else {
169 r = (object[]) Array.CreateInstance (attributeType, 0);
171 } else {
172 r = (object[]) Array.CreateInstance (res[0].GetType (), 1);
173 r[0] = res[0];
175 return r;
178 if (inherit && GetBase (obj) == null)
179 inherit = false;
181 // if AttributeType is sealed, and Inherited is set to false, then
182 // there's no use in scanning base types
183 if ((attributeType != null && attributeType.IsSealed) && inherit) {
184 AttributeUsageAttribute usageAttribute = RetrieveAttributeUsage (
185 attributeType);
186 if (!usageAttribute.Inherited)
187 inherit = false;
190 var initialSize = Math.Max (res.Length, 16);
191 List<Object> a = null;
192 ICustomAttributeProvider btype = obj;
193 object[] array;
195 /* Non-inherit case */
196 if (!inherit) {
197 if (attributeType == null) {
198 foreach (object attr in res) {
199 if (attr == null)
200 throw new CustomAttributeFormatException ("Invalid custom attribute format");
202 var result = new Attribute [res.Length];
203 res.CopyTo (result, 0);
204 return result;
207 a = new List<object> (initialSize);
208 foreach (object attr in res) {
209 if (attr == null)
210 throw new CustomAttributeFormatException ("Invalid custom attribute format");
212 Type attrType = attr.GetType ();
213 if (attributeType != null && !attributeType.IsAssignableFrom (attrType))
214 continue;
215 a.Add (attr);
218 if (attributeType == null || attributeType.IsValueType)
219 array = new Attribute [a.Count];
220 else
221 array = Array.CreateInstance (attributeType, a.Count) as object[];
222 a.CopyTo (array, 0);
223 return array;
226 /* Inherit case */
227 var attributeInfos = new Dictionary<Type, AttributeInfo> (initialSize);
228 int inheritanceLevel = 0;
229 a = new List<object> (initialSize);
231 do {
232 foreach (object attr in res) {
233 AttributeUsageAttribute usage;
234 if (attr == null)
235 throw new CustomAttributeFormatException ("Invalid custom attribute format");
237 Type attrType = attr.GetType ();
238 if (attributeType != null) {
239 if (!attributeType.IsAssignableFrom (attrType))
240 continue;
243 AttributeInfo firstAttribute;
244 if (attributeInfos.TryGetValue (attrType, out firstAttribute))
245 usage = firstAttribute.Usage;
246 else
247 usage = RetrieveAttributeUsage (attrType);
249 // only add attribute to the list of attributes if
250 // - we are on the first inheritance level, or the attribute can be inherited anyway
251 // and (
252 // - multiple attributes of the type are allowed
253 // or (
254 // - this is the first attribute we've discovered
255 // or
256 // - the attribute is on same inheritance level than the first
257 // attribute that was discovered for this attribute type ))
258 if ((inheritanceLevel == 0 || usage.Inherited) && (usage.AllowMultiple ||
259 (firstAttribute == null || (firstAttribute != null
260 && firstAttribute.InheritanceLevel == inheritanceLevel))))
261 a.Add (attr);
263 if (firstAttribute == null)
264 attributeInfos.Add (attrType, new AttributeInfo (usage, inheritanceLevel));
267 if ((btype = GetBase (btype)) != null) {
268 inheritanceLevel++;
269 res = GetCustomAttributesBase (btype, attributeType, true);
271 } while (inherit && btype != null);
273 if (attributeType == null || attributeType.IsValueType)
274 array = new Attribute [a.Count];
275 else
276 array = Array.CreateInstance (attributeType, a.Count) as object[];
278 // copy attributes to array
279 a.CopyTo (array, 0);
281 return array;
284 internal static object[] GetCustomAttributes (ICustomAttributeProvider obj, bool inherit)
286 if (obj == null)
287 throw new ArgumentNullException ("obj");
289 if (!inherit)
290 return (object[]) GetCustomAttributesBase (obj, null, false).Clone ();
292 return GetCustomAttributes (obj, typeof (MonoCustomAttrs), inherit);
295 [MethodImplAttribute (MethodImplOptions.InternalCall)]
296 [PreserveDependency(".ctor(System.Reflection.ConstructorInfo,System.Reflection.Assembly,System.IntPtr,System.UInt32)", "System.Reflection.CustomAttributeData")]
297 [PreserveDependency(".ctor(System.Reflection.MemberInfo,System.Object)", "System.Reflection.CustomAttributeNamedArgument")]
298 [PreserveDependency(".ctor(System.Type,System.Object)", "System.Reflection.CustomAttributeTypedArgument")]
299 static extern CustomAttributeData [] GetCustomAttributesDataInternal (ICustomAttributeProvider obj);
301 internal static IList<CustomAttributeData> GetCustomAttributesData (ICustomAttributeProvider obj, bool inherit = false)
303 if (obj == null)
304 throw new ArgumentNullException (nameof (obj));
306 if (!inherit)
307 return GetCustomAttributesDataBase (obj, null, false);
309 return GetCustomAttributesData (obj, typeof (MonoCustomAttrs), inherit);
312 internal static IList<CustomAttributeData> GetCustomAttributesData (ICustomAttributeProvider obj, Type attributeType, bool inherit)
314 if (obj == null)
315 throw new ArgumentNullException (nameof (obj));
316 if (attributeType == null)
317 throw new ArgumentNullException (nameof (attributeType));
319 if (attributeType == typeof (MonoCustomAttrs))
320 attributeType = null;
322 const string Message = "Invalid custom attribute data format";
323 IList<CustomAttributeData> r;
324 IList<CustomAttributeData> res = GetCustomAttributesDataBase (obj, attributeType, false);
325 // shortcut
326 if (!inherit && res.Count == 1) {
327 if (res [0] == null)
328 throw new CustomAttributeFormatException (Message);
329 if (attributeType != null) {
330 if (attributeType.IsAssignableFrom (res [0].AttributeType))
331 r = new CustomAttributeData[] { res [0] };
332 else
333 r = Array.Empty<CustomAttributeData> ();
334 } else {
335 r = new CustomAttributeData[] { res [0] };
338 return r;
341 if (inherit && GetBase (obj) == null)
342 inherit = false;
344 // if AttributeType is sealed, and Inherited is set to false, then
345 // there's no use in scanning base types
346 if ((attributeType != null && attributeType.IsSealed) && inherit) {
347 var usageAttribute = RetrieveAttributeUsage (attributeType);
348 if (!usageAttribute.Inherited)
349 inherit = false;
352 var initialSize = Math.Max (res.Count, 16);
353 List<CustomAttributeData> a = null;
354 ICustomAttributeProvider btype = obj;
356 /* Non-inherit case */
357 if (!inherit) {
358 if (attributeType == null) {
359 foreach (CustomAttributeData attrData in res) {
360 if (attrData == null)
361 throw new CustomAttributeFormatException (Message);
364 var result = new CustomAttributeData [res.Count];
365 res.CopyTo (result, 0);
366 return result;
367 } else {
368 a = new List<CustomAttributeData> (initialSize);
369 foreach (CustomAttributeData attrData in res) {
370 if (attrData == null)
371 throw new CustomAttributeFormatException (Message);
372 if (!attributeType.IsAssignableFrom (attrData.AttributeType))
373 continue;
374 a.Add (attrData);
377 return a.ToArray ();
381 /* Inherit case */
382 var attributeInfos = new Dictionary<Type, AttributeInfo> (initialSize);
383 int inheritanceLevel = 0;
384 a = new List<CustomAttributeData> (initialSize);
386 do {
387 foreach (CustomAttributeData attrData in res) {
388 AttributeUsageAttribute usage;
389 if (attrData == null)
390 throw new CustomAttributeFormatException (Message);
392 Type attrType = attrData.AttributeType;
393 if (attributeType != null) {
394 if (!attributeType.IsAssignableFrom (attrType))
395 continue;
398 AttributeInfo firstAttribute;
399 if (attributeInfos.TryGetValue (attrType, out firstAttribute))
400 usage = firstAttribute.Usage;
401 else
402 usage = RetrieveAttributeUsage (attrType);
404 // The same as for CustomAttributes.
406 // Only add attribute to the list of attributes if
407 // - we are on the first inheritance level, or the attribute can be inherited anyway
408 // and (
409 // - multiple attributes of the type are allowed
410 // or (
411 // - this is the first attribute we've discovered
412 // or
413 // - the attribute is on same inheritance level than the first
414 // attribute that was discovered for this attribute type ))
415 if ((inheritanceLevel == 0 || usage.Inherited) && (usage.AllowMultiple ||
416 (firstAttribute == null || (firstAttribute != null
417 && firstAttribute.InheritanceLevel == inheritanceLevel))))
418 a.Add(attrData);
420 if (firstAttribute == null)
421 attributeInfos.Add (attrType, new AttributeInfo (usage, inheritanceLevel));
424 if ((btype = GetBase (btype)) != null) {
425 inheritanceLevel++;
426 res = GetCustomAttributesDataBase (btype, attributeType, true);
428 } while (inherit && btype != null);
430 return a.ToArray ();
433 internal static IList<CustomAttributeData> GetCustomAttributesDataBase (ICustomAttributeProvider obj, Type attributeType, bool inheritedOnly)
435 CustomAttributeData[] attrsData;
436 if (IsUserCattrProvider (obj)) {
437 //FIXME resolve this case if it makes sense. Assign empty array for now.
438 //attrsData = obj.GetCustomAttributesData(attributeType, true);
439 attrsData = Array.Empty<CustomAttributeData> ();
440 } else
441 attrsData = GetCustomAttributesDataInternal (obj);
444 // All pseudo custom attributes are Inherited = false hence we can avoid
445 // building attributes data array which would be discarded by inherited checks
447 if (!inheritedOnly) {
448 CustomAttributeData[] pseudoAttrsData = GetPseudoCustomAttributesData (obj, attributeType);
449 if (pseudoAttrsData != null) {
450 if (attrsData.Length == 0)
451 return Array.AsReadOnly (pseudoAttrsData);
452 CustomAttributeData[] res = new CustomAttributeData [attrsData.Length + pseudoAttrsData.Length];
453 Array.Copy (attrsData, res, attrsData.Length);
454 Array.Copy (pseudoAttrsData, 0, res, attrsData.Length, pseudoAttrsData.Length);
455 return Array.AsReadOnly (res);
459 return Array.AsReadOnly (attrsData);
462 internal static CustomAttributeData[] GetPseudoCustomAttributesData (ICustomAttributeProvider obj, Type attributeType)
464 CustomAttributeData[] pseudoAttrsData = null;
466 /* FIXME: Add other types */
467 if (obj is RuntimeMethodInfo monoMethod)
468 pseudoAttrsData = monoMethod.GetPseudoCustomAttributesData ();
469 else if (obj is RuntimeFieldInfo fieldInfo)
470 pseudoAttrsData = fieldInfo.GetPseudoCustomAttributesData ();
471 else if (obj is RuntimeParameterInfo monoParamInfo)
472 pseudoAttrsData = monoParamInfo.GetPseudoCustomAttributesData ();
473 else if (obj is Type t)
474 pseudoAttrsData = GetPseudoCustomAttributesData (t);
476 if ((attributeType != null) && (pseudoAttrsData != null)) {
477 for (int i = 0; i < pseudoAttrsData.Length; ++i) {
478 if (attributeType.IsAssignableFrom (pseudoAttrsData [i].AttributeType)) {
479 if (pseudoAttrsData.Length == 1)
480 return pseudoAttrsData;
481 else
482 return new CustomAttributeData[] { pseudoAttrsData[i] };
486 return Array.Empty<CustomAttributeData> ();
489 return pseudoAttrsData;
492 static CustomAttributeData[] GetPseudoCustomAttributesData (Type type)
494 int count = 0;
495 var Attributes = type.Attributes;
497 /* IsSerializable returns true for delegates/enums as well */
498 if ((Attributes & TypeAttributes.Serializable) != 0)
499 count++;
500 if ((Attributes & TypeAttributes.Import) != 0)
501 count++;
503 if (count == 0)
504 return null;
505 CustomAttributeData[] attrsData = new CustomAttributeData [count];
506 count = 0;
508 if ((Attributes & TypeAttributes.Serializable) != 0)
509 attrsData [count++] = new CustomAttributeData ((typeof (SerializableAttribute)).GetConstructor (Type.EmptyTypes));
510 if ((Attributes & TypeAttributes.Import) != 0)
511 attrsData [count++] = new CustomAttributeData ((typeof (ComImportAttribute)).GetConstructor (Type.EmptyTypes));
513 return attrsData;
516 internal static bool IsDefined (ICustomAttributeProvider obj, Type attributeType, bool inherit)
518 if (attributeType == null)
519 throw new ArgumentNullException ("attributeType");
521 AttributeUsageAttribute usage = null;
522 do {
523 if (IsUserCattrProvider (obj))
524 return obj.IsDefined (attributeType, inherit);
526 if (IsDefinedInternal (obj, attributeType))
527 return true;
529 object[] pseudoAttrs = GetPseudoCustomAttributes (obj, attributeType);
530 if (pseudoAttrs != null) {
531 for (int i = 0; i < pseudoAttrs.Length; ++i)
532 if (attributeType.IsAssignableFrom (pseudoAttrs[i].GetType ()))
533 return true;
536 if (usage == null) {
537 if (!inherit)
538 return false;
540 usage = RetrieveAttributeUsage (attributeType);
541 if (!usage.Inherited)
542 return false;
545 obj = GetBase (obj);
546 } while (obj != null);
548 return false;
551 [MethodImplAttribute (MethodImplOptions.InternalCall)]
552 internal static extern bool IsDefinedInternal (ICustomAttributeProvider obj, Type AttributeType);
554 static PropertyInfo GetBasePropertyDefinition (RuntimePropertyInfo property)
556 MethodInfo method = property.GetGetMethod (true);
557 if (method == null || !method.IsVirtual)
558 method = property.GetSetMethod (true);
559 if (method == null || !method.IsVirtual)
560 return null;
562 MethodInfo baseMethod = ((RuntimeMethodInfo)method).GetBaseMethod ();
563 if (baseMethod != null && baseMethod != method) {
564 ParameterInfo[] parameters = property.GetIndexParameters ();
565 if (parameters != null && parameters.Length > 0) {
566 Type[] paramTypes = new Type[parameters.Length];
567 for (int i=0; i < paramTypes.Length; i++)
568 paramTypes[i] = parameters[i].ParameterType;
569 return baseMethod.DeclaringType.GetProperty (property.Name, property.PropertyType,
570 paramTypes);
571 } else {
572 return baseMethod.DeclaringType.GetProperty (property.Name, property.PropertyType);
575 return null;
579 static EventInfo GetBaseEventDefinition (RuntimeEventInfo evt)
581 MethodInfo method = evt.GetAddMethod (true);
582 if (method == null || !method.IsVirtual)
583 method = evt.GetRaiseMethod (true);
584 if (method == null || !method.IsVirtual)
585 method = evt.GetRemoveMethod (true);
586 if (method == null || !method.IsVirtual)
587 return null;
589 MethodInfo baseMethod = ((RuntimeMethodInfo)method).GetBaseMethod ();
590 if (baseMethod != null && baseMethod != method) {
591 BindingFlags flags = method.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
592 flags |= method.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
594 return baseMethod.DeclaringType.GetEvent (evt.Name, flags);
596 return null;
599 // Handles Type, RuntimePropertyInfo and RuntimeMethodInfo.
600 // The runtime has also cases for RuntimeEventInfo, RuntimeFieldInfo, Assembly and ParameterInfo,
601 // but for those we return null here.
602 static ICustomAttributeProvider GetBase (ICustomAttributeProvider obj)
604 if (obj == null)
605 return null;
607 if (obj is Type)
608 return ((Type) obj).BaseType;
610 MethodInfo method = null;
611 if (obj is RuntimePropertyInfo)
612 return GetBasePropertyDefinition ((RuntimePropertyInfo) obj);
613 else if (obj is RuntimeEventInfo)
614 return GetBaseEventDefinition ((RuntimeEventInfo)obj);
615 else if (obj is RuntimeMethodInfo)
616 method = (MethodInfo) obj;
617 if (obj is RuntimeParameterInfo parinfo) {
618 var member = parinfo.Member;
619 if (member is MethodInfo) {
620 method = (MethodInfo)member;
621 MethodInfo bmethod = ((RuntimeMethodInfo)method).GetBaseMethod ();
622 if (bmethod == method)
623 return null;
624 return bmethod.GetParameters ()[parinfo.Position];
628 * ParameterInfo -> null
629 * Assembly -> null
630 * RuntimeEventInfo -> null
631 * RuntimeFieldInfo -> null
633 if (method == null || !method.IsVirtual)
634 return null;
636 MethodInfo baseMethod = ((RuntimeMethodInfo)method).GetBaseMethod ();
637 if (baseMethod == method)
638 return null;
640 return baseMethod;
643 private static AttributeUsageAttribute RetrieveAttributeUsageNoCache (Type attributeType)
645 if (attributeType == typeof (AttributeUsageAttribute))
646 /* Avoid endless recursion */
647 return new AttributeUsageAttribute (AttributeTargets.Class);
649 AttributeUsageAttribute usageAttribute = null;
650 object[] attribs = GetCustomAttributes (attributeType, typeof(AttributeUsageAttribute), false);
651 if (attribs.Length == 0)
653 // if no AttributeUsage was defined on the attribute level, then
654 // try to retrieve if from its base type
655 if (attributeType.BaseType != null)
657 usageAttribute = RetrieveAttributeUsage (attributeType.BaseType);
660 if (usageAttribute != null)
662 // return AttributeUsage of base class
663 return usageAttribute;
666 // return default AttributeUsageAttribute if no AttributeUsage
667 // was defined on attribute, or its base class
668 return DefaultAttributeUsage;
670 // check if more than one AttributeUsageAttribute has been specified
671 // on the type
672 // NOTE: compilers should prevent this, but that doesn't prevent
673 // anyone from using IL ofcourse
674 if (attribs.Length > 1)
676 throw new FormatException ("Duplicate AttributeUsageAttribute cannot be specified on an attribute type.");
679 return ((AttributeUsageAttribute) attribs[0]);
682 static AttributeUsageAttribute RetrieveAttributeUsage (Type attributeType)
684 AttributeUsageAttribute usageAttribute = null;
685 /* Usage a thread-local cache to speed this up, since it is called a lot from GetCustomAttributes () */
686 if (usage_cache == null)
687 usage_cache = new Dictionary<Type, AttributeUsageAttribute> ();
688 if (usage_cache.TryGetValue (attributeType, out usageAttribute))
689 return usageAttribute;
690 usageAttribute = RetrieveAttributeUsageNoCache (attributeType);
691 usage_cache [attributeType] = usageAttribute;
692 return usageAttribute;
695 private static readonly AttributeUsageAttribute DefaultAttributeUsage =
696 new AttributeUsageAttribute (AttributeTargets.All);
698 private class AttributeInfo
700 private AttributeUsageAttribute _usage;
701 private int _inheritanceLevel;
703 public AttributeInfo (AttributeUsageAttribute usage, int inheritanceLevel)
705 _usage = usage;
706 _inheritanceLevel = inheritanceLevel;
709 public AttributeUsageAttribute Usage
713 return _usage;
717 public int InheritanceLevel
721 return _inheritanceLevel;