internal static object[] GetCustomAttributes (ICustomAttributeProvider obj, Type attributeType, bool inherit)
{
if (obj == null)
throw new ArgumentNullException ("obj");
if (attributeType == null)
throw new ArgumentNullException ("attributeType");
if (attributeType == typeof (MonoCustomAttrs))
attributeType = null;
object[] r;
object[] res = GetCustomAttributesBase (obj, attributeType);
// shortcut
if (!inherit && res.Length == 1)
{
if (res [0] == null)
throw new CustomAttributeFormatException ("Invalid custom attribute format");
if (attributeType != null)
{
if (attributeType.IsAssignableFrom (res[0].GetType ()))
{
r = (object[]) Array.CreateInstance (attributeType, 1);
r[0] = res[0];
}
else
{
r = (object[]) Array.CreateInstance (attributeType, 0);
}
}
else
{
r = (object[]) Array.CreateInstance (res[0].GetType (), 1);
r[0] = res[0];
}
return r;
}
// if AttributeType is sealed, and Inherited is set to false, then
// there's no use in scanning base types
if ((attributeType != null && attributeType.IsSealed) && inherit)
{
AttributeUsageAttribute usageAttribute = RetrieveAttributeUsage (
attributeType);
if (!usageAttribute.Inherited)
{
inherit = false;
}
}
int initialSize = res.Length < 16 ? res.Length : 16;
Hashtable attributeInfos = new Hashtable (initialSize);
ArrayList a = new ArrayList (initialSize);
ICustomAttributeProvider btype = obj;
int inheritanceLevel = 0;
do
{
foreach (object attr in res)
{
AttributeUsageAttribute usage;
if (attr == null)
throw new CustomAttributeFormatException ("Invalid custom attribute format");
Type attrType = attr.GetType ();
if (attributeType != null)
{
if (!attributeType.IsAssignableFrom (attrType))
{
continue;
}
}
AttributeInfo firstAttribute = (AttributeInfo) attributeInfos[attrType];
if (firstAttribute != null)
{
usage = firstAttribute.Usage;
}
else
{
usage = RetrieveAttributeUsage (attrType);
}
// only add attribute to the list of attributes if
// - we are on the first inheritance level, or the attribute can be inherited anyway
// and (
// - multiple attributes of the type are allowed
// or (
// - this is the first attribute we've discovered
// or
// - the attribute is on same inheritance level than the first
// attribute that was discovered for this attribute type ))
if ((inheritanceLevel == 0 || usage.Inherited) && (usage.AllowMultiple ||
(firstAttribute == null || (firstAttribute != null
&& firstAttribute.InheritanceLevel == inheritanceLevel))))
{
a.Add (attr);
}
if (firstAttribute == null)
{
attributeInfos.Add (attrType, new AttributeInfo (usage, inheritanceLevel));
}
}
if ((btype = GetBase (btype)) != null)
{
inheritanceLevel++;
res = GetCustomAttributesBase (btype, attributeType);
}
} while (inherit && btype != null);
object[] array = null;
if (attributeType == null || attributeType.IsValueType)
{
array = (object[]) Array.CreateInstance (typeof(Attribute), a.Count);
}
else
{
array = Array.CreateInstance (attributeType, a.Count) as object[];
}
// copy attributes to array
a.CopyTo (array, 0);
return array;
}