Mono friendly Attribute
[mono-project.git] / mcs / class / referencesource / mscorlib / system / attribute.cs
blob76293f5a8abd4848d17215144d7b0d977b42839a
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
7 namespace System {
9 using System;
10 using System.Reflection;
11 using System.Collections.Generic;
12 using System.Runtime.InteropServices;
13 using System.Globalization;
14 using System.Diagnostics.Contracts;
15 using System.Security;
16 using System.Security.Permissions;
18 [Serializable]
19 [AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple=false)]
20 [ClassInterface(ClassInterfaceType.None)]
21 [ComDefaultInterface(typeof(_Attribute))]
22 [System.Runtime.InteropServices.ComVisible(true)]
23 public abstract partial class Attribute : _Attribute
25 #region Private Statics
26 #if !MONO
27 #region PropertyInfo
28 private static Attribute[] InternalGetCustomAttributes(PropertyInfo element, Type type, bool inherit)
30 Contract.Requires(element != null);
31 Contract.Requires(type != null);
32 Contract.Requires(type.IsSubclassOf(typeof(Attribute)) || type == typeof(Attribute));
34 // walk up the hierarchy chain
35 Attribute[] attributes = (Attribute[])element.GetCustomAttributes(type, inherit);
37 if (!inherit)
38 return attributes;
40 // create the hashtable that keeps track of inherited types
41 Dictionary<Type, AttributeUsageAttribute> types = new Dictionary<Type, AttributeUsageAttribute>(11);
43 // create an array list to collect all the requested attibutes
44 List<Attribute> attributeList = new List<Attribute>();
45 CopyToArrayList(attributeList, attributes, types);
47 PropertyInfo baseProp = GetParentDefinition(element);
48 while (baseProp != null)
50 attributes = GetCustomAttributes(baseProp, type, false);
51 AddAttributesToList(attributeList, attributes, types);
52 baseProp = GetParentDefinition(baseProp);
54 Array array = CreateAttributeArrayHelper(type, attributeList.Count);
55 Array.Copy(attributeList.ToArray(), 0, array, 0, attributeList.Count);
56 return (Attribute[])array;
59 private static bool InternalIsDefined(PropertyInfo element, Type attributeType, bool inherit)
61 // walk up the hierarchy chain
62 if (element.IsDefined(attributeType, inherit))
63 return true;
65 if (inherit)
67 AttributeUsageAttribute usage = InternalGetAttributeUsage(attributeType);
69 if (!usage.Inherited)
70 return false;
72 PropertyInfo baseProp = GetParentDefinition(element);
74 while (baseProp != null)
76 if (baseProp.IsDefined(attributeType, false))
77 return true;
79 baseProp = GetParentDefinition(baseProp);
83 return false;
86 private static PropertyInfo GetParentDefinition(PropertyInfo property)
88 Contract.Requires(property != null);
90 // for the current property get the base class of the getter and the setter, they might be different
91 // note that this only works for RuntimeMethodInfo
92 MethodInfo propAccessor = property.GetGetMethod(true);
94 if (propAccessor == null)
95 propAccessor = property.GetSetMethod(true);
97 RuntimeMethodInfo rtPropAccessor = propAccessor as RuntimeMethodInfo;
99 if (rtPropAccessor != null)
101 rtPropAccessor = rtPropAccessor.GetParentDefinition();
103 if (rtPropAccessor != null)
105 #if FEATURE_LEGACYNETCF
106 // Mimicing NetCF which only looks for public properties.
107 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
108 return rtPropAccessor.DeclaringType.GetProperty(property.Name, property.PropertyType);
109 #endif //FEATURE_LEGACYNETCF
111 // There is a public overload of Type.GetProperty that takes both a BingingFlags enum and a return type.
112 // However, we cannot use that because it doesn't accept null for "types".
113 return rtPropAccessor.DeclaringType.GetProperty(
114 property.Name,
115 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
116 property.PropertyType);
120 return null;
123 #endregion
125 #region EventInfo
126 private static Attribute[] InternalGetCustomAttributes(EventInfo element, Type type, bool inherit)
128 Contract.Requires(element != null);
129 Contract.Requires(type != null);
130 Contract.Requires(type.IsSubclassOf(typeof(Attribute)) || type == typeof(Attribute));
132 // walk up the hierarchy chain
133 Attribute[] attributes = (Attribute[])element.GetCustomAttributes(type, inherit);
134 if (inherit)
136 // create the hashtable that keeps track of inherited types
137 Dictionary<Type, AttributeUsageAttribute> types = new Dictionary<Type, AttributeUsageAttribute>(11);
138 // create an array list to collect all the requested attibutes
139 List<Attribute> attributeList = new List<Attribute>();
140 CopyToArrayList(attributeList, attributes, types);
142 EventInfo baseEvent = GetParentDefinition(element);
143 while (baseEvent != null)
145 attributes = GetCustomAttributes(baseEvent, type, false);
146 AddAttributesToList(attributeList, attributes, types);
147 baseEvent = GetParentDefinition(baseEvent);
149 Array array = CreateAttributeArrayHelper(type, attributeList.Count);
150 Array.Copy(attributeList.ToArray(), 0, array, 0, attributeList.Count);
151 return (Attribute[])array;
153 else
154 return attributes;
157 private static EventInfo GetParentDefinition(EventInfo ev)
159 Contract.Requires(ev != null);
161 // note that this only works for RuntimeMethodInfo
162 MethodInfo add = ev.GetAddMethod(true);
164 RuntimeMethodInfo rtAdd = add as RuntimeMethodInfo;
166 if (rtAdd != null)
168 rtAdd = rtAdd.GetParentDefinition();
169 if (rtAdd != null)
170 return rtAdd.DeclaringType.GetEvent(ev.Name);
172 return null;
175 private static bool InternalIsDefined (EventInfo element, Type attributeType, bool inherit)
177 Contract.Requires(element != null);
179 // walk up the hierarchy chain
180 if (element.IsDefined(attributeType, inherit))
181 return true;
183 if (inherit)
185 AttributeUsageAttribute usage = InternalGetAttributeUsage(attributeType);
187 if (!usage.Inherited)
188 return false;
190 EventInfo baseEvent = GetParentDefinition(element);
192 while (baseEvent != null)
194 if (baseEvent.IsDefined(attributeType, false))
195 return true;
196 baseEvent = GetParentDefinition(baseEvent);
200 return false;
203 #endregion
205 #region ParameterInfo
206 private static ParameterInfo GetParentDefinition(ParameterInfo param)
208 Contract.Requires(param != null);
210 // note that this only works for RuntimeMethodInfo
211 RuntimeMethodInfo rtMethod = param.Member as RuntimeMethodInfo;
213 if (rtMethod != null)
215 rtMethod = rtMethod.GetParentDefinition();
217 if (rtMethod != null)
219 // Find the ParameterInfo on this method
220 ParameterInfo[] parameters = rtMethod.GetParameters();
221 return parameters[param.Position]; // Point to the correct ParameterInfo of the method
224 return null;
227 private static Attribute[] InternalParamGetCustomAttributes(ParameterInfo param, Type type, bool inherit)
229 Contract.Requires(param != null);
231 // For ParameterInfo's we need to make sure that we chain through all the MethodInfo's in the inheritance chain that
232 // have this ParameterInfo defined. .We pick up all the CustomAttributes for the starting ParameterInfo. We need to pick up only attributes
233 // that are marked inherited from the remainder of the MethodInfo's in the inheritance chain.
234 // For MethodInfo's on an interface we do not do an inheritance walk so the default ParameterInfo attributes are returned.
235 // For MethodInfo's on a class we walk up the inheritance chain but do not look at the MethodInfo's on the interfaces that the
236 // class inherits from and return the respective ParameterInfo attributes
238 List<Type> disAllowMultiple = new List<Type>();
239 Object [] objAttr;
241 if (type == null)
242 type = typeof(Attribute);
244 objAttr = param.GetCustomAttributes(type, false);
246 for (int i =0;i < objAttr.Length;i++)
248 Type objType = objAttr[i].GetType();
249 AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);
250 if (attribUsage.AllowMultiple == false)
251 disAllowMultiple.Add(objType);
254 // Get all the attributes that have Attribute as the base class
255 Attribute [] ret = null;
256 if (objAttr.Length == 0)
257 ret = CreateAttributeArrayHelper(type,0);
258 else
259 ret = (Attribute[])objAttr;
261 if (param.Member.DeclaringType == null) // This is an interface so we are done.
262 return ret;
264 if (!inherit)
265 return ret;
267 ParameterInfo baseParam = GetParentDefinition(param);
269 while (baseParam != null)
271 objAttr = baseParam.GetCustomAttributes(type, false);
273 int count = 0;
274 for (int i =0;i < objAttr.Length;i++)
276 Type objType = objAttr[i].GetType();
277 AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);
279 if ((attribUsage.Inherited) && (disAllowMultiple.Contains(objType) == false))
281 if (attribUsage.AllowMultiple == false)
282 disAllowMultiple.Add(objType);
283 count++;
285 else
286 objAttr[i] = null;
289 // Get all the attributes that have Attribute as the base class
290 Attribute [] attributes = CreateAttributeArrayHelper(type,count);
292 count = 0;
293 for (int i =0;i < objAttr.Length;i++)
295 if (objAttr[i] != null)
297 attributes[count] = (Attribute)objAttr[i];
298 count++;
302 Attribute [] temp = ret;
303 ret = CreateAttributeArrayHelper(type,temp.Length + count);
304 Array.Copy(temp,ret,temp.Length);
306 int offset = temp.Length;
308 for (int i =0;i < attributes.Length;i++)
309 ret[offset + i] = attributes[i];
311 baseParam = GetParentDefinition(baseParam);
314 return ret;
317 private static bool InternalParamIsDefined(ParameterInfo param, Type type, bool inherit)
319 Contract.Requires(param != null);
320 Contract.Requires(type != null);
322 // For ParameterInfo's we need to make sure that we chain through all the MethodInfo's in the inheritance chain.
323 // We pick up all the CustomAttributes for the starting ParameterInfo. We need to pick up only attributes
324 // that are marked inherited from the remainder of the ParameterInfo's in the inheritance chain.
325 // For MethodInfo's on an interface we do not do an inheritance walk. For ParameterInfo's on a
326 // Class we walk up the inheritance chain but do not look at the MethodInfo's on the interfaces that the class inherits from.
328 if (param.IsDefined(type, false))
329 return true;
331 if (param.Member.DeclaringType == null || !inherit) // This is an interface so we are done.
332 return false;
334 ParameterInfo baseParam = GetParentDefinition(param);
336 while (baseParam != null)
338 Object[] objAttr = baseParam.GetCustomAttributes(type, false);
340 for (int i =0; i < objAttr.Length; i++)
342 Type objType = objAttr[i].GetType();
343 AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);
345 if ((objAttr[i] is Attribute) && (attribUsage.Inherited))
346 return true;
349 baseParam = GetParentDefinition(baseParam);
352 return false;
355 #endregion
357 #region Utility
358 private static void CopyToArrayList(List<Attribute> attributeList,Attribute[] attributes,Dictionary<Type, AttributeUsageAttribute> types)
360 for (int i = 0; i < attributes.Length; i++)
362 attributeList.Add(attributes[i]);
364 Type attrType = attributes[i].GetType();
366 if (!types.ContainsKey(attrType))
367 types[attrType] = InternalGetAttributeUsage(attrType);
371 private static void AddAttributesToList(List<Attribute> attributeList, Attribute[] attributes, Dictionary<Type, AttributeUsageAttribute> types)
373 for (int i = 0; i < attributes.Length; i++)
375 Type attrType = attributes[i].GetType();
376 AttributeUsageAttribute usage = null;
377 types.TryGetValue(attrType, out usage);
379 if (usage == null)
381 // the type has never been seen before if it's inheritable add it to the list
382 usage = InternalGetAttributeUsage(attrType);
383 types[attrType] = usage;
385 if (usage.Inherited)
386 attributeList.Add(attributes[i]);
388 else if (usage.Inherited && usage.AllowMultiple)
390 // we saw this type already add it only if it is inheritable and it does allow multiple
391 attributeList.Add(attributes[i]);
396 private static AttributeUsageAttribute InternalGetAttributeUsage(Type type)
398 // Check if the custom attributes is Inheritable
399 Object [] obj = type.GetCustomAttributes(typeof(AttributeUsageAttribute), false);
401 if (obj.Length == 1)
402 return (AttributeUsageAttribute)obj[0];
404 if (obj.Length == 0)
405 return AttributeUsageAttribute.Default;
407 throw new FormatException(
408 Environment.GetResourceString("Format_AttributeUsage", type));
411 [System.Security.SecuritySafeCritical]
412 private static Attribute[] CreateAttributeArrayHelper(Type elementType, int elementCount)
414 return (Attribute[])Array.UnsafeCreateInstance(elementType, elementCount);
416 #endregion
417 #endif
418 #endregion
420 #region Public Statics
422 #region MemberInfo
423 public static Attribute[] GetCustomAttributes(MemberInfo element, Type type)
425 return GetCustomAttributes(element, type, true);
428 public static Attribute[] GetCustomAttributes(MemberInfo element, Type type, bool inherit)
430 if (element == null)
431 throw new ArgumentNullException("element");
433 if (type == null)
434 throw new ArgumentNullException("type");
436 if (!type.IsSubclassOf(typeof(Attribute)) && type != typeof(Attribute))
437 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
438 Contract.EndContractBlock();
440 switch (element.MemberType)
442 case MemberTypes.Property:
443 return InternalGetCustomAttributes((PropertyInfo)element, type, inherit);
445 case MemberTypes.Event:
446 return InternalGetCustomAttributes((EventInfo)element, type, inherit);
448 default:
449 return element.GetCustomAttributes(type, inherit) as Attribute[];
453 public static Attribute[] GetCustomAttributes(MemberInfo element)
455 return GetCustomAttributes(element, true);
458 public static Attribute[] GetCustomAttributes(MemberInfo element, bool inherit)
460 if (element == null)
461 throw new ArgumentNullException("element");
462 Contract.EndContractBlock();
464 switch (element.MemberType)
466 case MemberTypes.Property:
467 return InternalGetCustomAttributes((PropertyInfo)element, typeof(Attribute), inherit);
469 case MemberTypes.Event:
470 return InternalGetCustomAttributes((EventInfo)element, typeof(Attribute), inherit);
472 default:
473 return element.GetCustomAttributes(typeof(Attribute), inherit) as Attribute[];
477 public static bool IsDefined(MemberInfo element, Type attributeType)
479 return IsDefined(element, attributeType, true);
482 public static bool IsDefined(MemberInfo element, Type attributeType, bool inherit)
484 // Returns true if a custom attribute subclass of attributeType class/interface with inheritance walk
485 if (element == null)
486 throw new ArgumentNullException("element");
488 if (attributeType == null)
489 throw new ArgumentNullException("attributeType");
491 if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
492 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
493 Contract.EndContractBlock();
495 switch(element.MemberType)
497 case MemberTypes.Property:
498 return InternalIsDefined((PropertyInfo)element, attributeType, inherit);
500 case MemberTypes.Event:
501 return InternalIsDefined((EventInfo)element, attributeType, inherit);
503 default:
504 return element.IsDefined(attributeType, inherit);
509 public static Attribute GetCustomAttribute(MemberInfo element, Type attributeType)
511 return GetCustomAttribute(element, attributeType, true);
514 public static Attribute GetCustomAttribute(MemberInfo element, Type attributeType, bool inherit)
516 Attribute[] attrib = GetCustomAttributes(element, attributeType, inherit);
518 if (attrib == null || attrib.Length == 0)
519 return null;
521 if (attrib.Length == 1)
522 return attrib[0];
524 throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
527 #endregion
529 #region ParameterInfo
530 public static Attribute[] GetCustomAttributes(ParameterInfo element)
532 return GetCustomAttributes(element, true);
535 public static Attribute[] GetCustomAttributes(ParameterInfo element, Type attributeType)
537 return (Attribute[])GetCustomAttributes(element, attributeType, true);
540 public static Attribute[] GetCustomAttributes(ParameterInfo element, Type attributeType, bool inherit)
542 if (element == null)
543 throw new ArgumentNullException("element");
545 if (attributeType == null)
546 throw new ArgumentNullException("attributeType");
548 if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
549 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
551 if (element.Member == null)
552 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), "element");
554 Contract.EndContractBlock();
556 MemberInfo member = element.Member;
557 if (member.MemberType == MemberTypes.Method && inherit)
558 return InternalParamGetCustomAttributes(element, attributeType, inherit) as Attribute[];
560 return element.GetCustomAttributes(attributeType, inherit) as Attribute[];
563 public static Attribute[] GetCustomAttributes(ParameterInfo element, bool inherit)
565 if (element == null)
566 throw new ArgumentNullException("element");
568 if (element.Member == null)
569 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), "element");
571 Contract.EndContractBlock();
573 MemberInfo member = element.Member;
574 if (member.MemberType == MemberTypes.Method && inherit)
575 return InternalParamGetCustomAttributes(element, null, inherit) as Attribute[];
577 return element.GetCustomAttributes(typeof(Attribute), inherit) as Attribute[];
580 public static bool IsDefined(ParameterInfo element, Type attributeType)
582 return IsDefined(element, attributeType, true);
585 public static bool IsDefined(ParameterInfo element, Type attributeType, bool inherit)
587 // Returns true is a custom attribute subclass of attributeType class/interface with inheritance walk
588 if (element == null)
589 throw new ArgumentNullException("element");
591 if (attributeType == null)
592 throw new ArgumentNullException("attributeType");
594 if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
595 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
596 Contract.EndContractBlock();
598 MemberInfo member = element.Member;
600 switch(member.MemberType)
602 case MemberTypes.Method: // We need to climb up the member hierarchy
603 return InternalParamIsDefined(element, attributeType, inherit);
605 case MemberTypes.Constructor:
606 return element.IsDefined(attributeType, false);
608 case MemberTypes.Property:
609 return element.IsDefined(attributeType, false);
611 default:
612 Contract.Assert(false, "Invalid type for ParameterInfo member in Attribute class");
613 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParamInfo"));
617 public static Attribute GetCustomAttribute(ParameterInfo element, Type attributeType)
619 return GetCustomAttribute(element, attributeType, true);
622 public static Attribute GetCustomAttribute(ParameterInfo element, Type attributeType, bool inherit)
624 // Returns an Attribute of base class/inteface attributeType on the ParameterInfo or null if none exists.
625 // throws an AmbiguousMatchException if there are more than one defined.
626 Attribute[] attrib = GetCustomAttributes(element, attributeType, inherit);
628 if (attrib == null || attrib.Length == 0)
629 return null;
631 if (attrib.Length == 0)
632 return null;
634 if (attrib.Length == 1)
635 return attrib[0];
637 throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
640 #endregion
642 #region Module
643 public static Attribute[] GetCustomAttributes(Module element, Type attributeType)
645 return GetCustomAttributes (element, attributeType, true);
648 public static Attribute[] GetCustomAttributes(Module element)
650 return GetCustomAttributes(element, true);
653 public static Attribute[] GetCustomAttributes(Module element, bool inherit)
655 if (element == null)
656 throw new ArgumentNullException("element");
657 Contract.EndContractBlock();
659 return (Attribute[])element.GetCustomAttributes(typeof(Attribute), inherit);
662 public static Attribute[] GetCustomAttributes(Module element, Type attributeType, bool inherit)
664 if (element == null)
665 throw new ArgumentNullException("element");
667 if (attributeType == null)
668 throw new ArgumentNullException("attributeType");
670 if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
671 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
672 Contract.EndContractBlock();
674 return (Attribute[])element.GetCustomAttributes(attributeType, inherit);
677 public static bool IsDefined(Module element, Type attributeType)
679 return IsDefined(element, attributeType, false);
682 public static bool IsDefined(Module element, Type attributeType, bool inherit)
684 // Returns true is a custom attribute subclass of attributeType class/interface with no inheritance walk
685 if (element == null)
686 throw new ArgumentNullException("element");
688 if (attributeType == null)
689 throw new ArgumentNullException("attributeType");
691 if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
692 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
693 Contract.EndContractBlock();
695 return element.IsDefined(attributeType,false);
698 public static Attribute GetCustomAttribute(Module element, Type attributeType)
700 return GetCustomAttribute(element, attributeType, true);
703 public static Attribute GetCustomAttribute(Module element, Type attributeType, bool inherit)
705 // Returns an Attribute of base class/inteface attributeType on the Module or null if none exists.
706 // throws an AmbiguousMatchException if there are more than one defined.
707 Attribute[] attrib = GetCustomAttributes(element,attributeType,inherit);
709 if (attrib == null || attrib.Length == 0)
710 return null;
712 if (attrib.Length == 1)
713 return attrib[0];
715 throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
718 #endregion
720 #region Assembly
721 public static Attribute[] GetCustomAttributes(Assembly element, Type attributeType)
723 return GetCustomAttributes(element, attributeType, true);
726 public static Attribute[] GetCustomAttributes(Assembly element, Type attributeType, bool inherit)
728 if (element == null)
729 throw new ArgumentNullException("element");
731 if (attributeType == null)
732 throw new ArgumentNullException("attributeType");
734 if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
735 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
736 Contract.EndContractBlock();
738 return (Attribute[])element.GetCustomAttributes(attributeType, inherit);
741 public static Attribute[] GetCustomAttributes(Assembly element)
743 return GetCustomAttributes(element, true);
746 public static Attribute[] GetCustomAttributes(Assembly element, bool inherit)
748 if (element == null)
749 throw new ArgumentNullException("element");
750 Contract.EndContractBlock();
752 return (Attribute[])element.GetCustomAttributes(typeof(Attribute), inherit);
755 public static bool IsDefined (Assembly element, Type attributeType)
757 return IsDefined (element, attributeType, true);
760 public static bool IsDefined (Assembly element, Type attributeType, bool inherit)
762 // Returns true is a custom attribute subclass of attributeType class/interface with no inheritance walk
763 if (element == null)
764 throw new ArgumentNullException("element");
766 if (attributeType == null)
767 throw new ArgumentNullException("attributeType");
769 if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
770 throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
771 Contract.EndContractBlock();
773 return element.IsDefined(attributeType, false);
776 public static Attribute GetCustomAttribute(Assembly element, Type attributeType)
778 return GetCustomAttribute (element, attributeType, true);
781 public static Attribute GetCustomAttribute(Assembly element, Type attributeType, bool inherit)
783 // Returns an Attribute of base class/inteface attributeType on the Assembly or null if none exists.
784 // throws an AmbiguousMatchException if there are more than one defined.
785 Attribute[] attrib = GetCustomAttributes(element,attributeType,inherit);
787 if (attrib == null || attrib.Length == 0)
788 return null;
790 if (attrib.Length == 1)
791 return attrib[0];
793 throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
796 #endregion
798 #endregion
800 #region Constructor
801 protected Attribute() { }
802 #endregion
804 #region Object Overrides
805 [SecuritySafeCritical]
806 public override bool Equals(Object obj)
808 if (obj == null)
809 return false;
811 RuntimeType thisType = (RuntimeType)this.GetType();
812 RuntimeType thatType = (RuntimeType)obj.GetType();
814 if (thatType != thisType)
815 return false;
817 Object thisObj = this;
818 Object thisResult, thatResult;
820 FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
822 for (int i = 0; i < thisFields.Length; i++)
824 // Visibility check and consistency check are not necessary.
825 thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj);
826 thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj);
828 if (!AreFieldValuesEqual(thisResult, thatResult))
830 return false;
834 return true;
837 // Compares values of custom-attribute fields.
838 private static bool AreFieldValuesEqual(Object thisValue, Object thatValue)
840 if (thisValue == null && thatValue == null)
841 return true;
842 if (thisValue == null || thatValue == null)
843 return false;
845 if (thisValue.GetType().IsArray)
847 // Ensure both are arrays of the same type.
848 if (!thisValue.GetType().Equals(thatValue.GetType()))
850 return false;
853 Array thisValueArray = thisValue as Array;
854 Array thatValueArray = thatValue as Array;
855 if (thisValueArray.Length != thatValueArray.Length)
857 return false;
860 // Attributes can only contain single-dimension arrays, so we don't need to worry about
861 // multidimensional arrays.
862 Contract.Assert(thisValueArray.Rank == 1 && thatValueArray.Rank == 1);
863 for (int j = 0; j < thisValueArray.Length; j++)
865 if (!AreFieldValuesEqual(thisValueArray.GetValue(j), thatValueArray.GetValue(j)))
867 return false;
871 else
873 // An object of type Attribute will cause a stack overflow.
874 // However, this should never happen because custom attributes cannot contain values other than
875 // constants, single-dimensional arrays and typeof expressions.
876 Contract.Assert(!(thisValue is Attribute));
877 if (!thisValue.Equals(thatValue))
878 return false;
881 return true;
884 [SecuritySafeCritical]
885 public override int GetHashCode()
887 Type type = GetType();
889 FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
890 Object vThis = null;
892 for (int i = 0; i < fields.Length; i++)
894 // Visibility check and consistency check are not necessary.
895 Object fieldValue = ((RtFieldInfo)fields[i]).UnsafeGetValue(this);
897 // The hashcode of an array ignores the contents of the array, so it can produce
898 // different hashcodes for arrays with the same contents.
899 // Since we do deep comparisons of arrays in Equals(), this means Equals and GetHashCode will
900 // be inconsistent for arrays. Therefore, we ignore hashes of arrays.
901 if (fieldValue != null && !fieldValue.GetType().IsArray)
902 vThis = fieldValue;
904 if (vThis != null)
905 break;
908 if (vThis != null)
909 return vThis.GetHashCode();
911 return type.GetHashCode();
913 #endregion
915 #region Public Virtual Members
916 public virtual Object TypeId { get { return GetType(); } }
918 public virtual bool Match(Object obj) { return Equals(obj); }
919 #endregion
921 #region Public Members
922 public virtual bool IsDefaultAttribute() { return false; }
923 #endregion
925 void _Attribute.GetTypeInfoCount(out uint pcTInfo)
927 throw new NotImplementedException();
930 void _Attribute.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
932 throw new NotImplementedException();
935 void _Attribute.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
937 throw new NotImplementedException();
940 void _Attribute.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
942 throw new NotImplementedException();