internal static Object[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool inherit)
{
if (type.GetElementType() != null)
return (caType.IsValueType) ? new object[0] : (Object[])Array.CreateInstance(caType, 0);
if (type.IsGenericType && !type.IsGenericTypeDefinition)
type = type.GetGenericTypeDefinition() as RuntimeType;
int pcaCount = 0;
Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(type, caType, true, out pcaCount);
// if we are asked to go up the hierarchy chain we have to do it now and regardless of the
// attribute usage for the specific attribute because a derived attribute may override the usage...
// ... however if the attribute is sealed we can rely on the attribute usage
if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited))
{
object[] attributes = GetCustomAttributes(type.Module, type.MetadataToken, pcaCount, caType);
if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
return attributes;
}
List<object> result = new List<object>();
bool mustBeInheritable = false;
bool useObjectArray = (caType == null || caType.IsValueType || caType.ContainsGenericParameters);
Type arrayType = useObjectArray ? typeof(object) : caType;
while (pcaCount > 0)
result.Add(pca[--pcaCount]);
while (type != typeof(object) && type != null)
{
object[] attributes = GetCustomAttributes(type.Module, type.MetadataToken, 0, caType, mustBeInheritable, result);
mustBeInheritable = true;
for (int i = 0; i < attributes.Length; i++)
result.Add(attributes[i]);
type = type.BaseType as RuntimeType;
}
object[] typedResult = Array.CreateInstance(arrayType, result.Count) as object[];
Array.Copy(result.ToArray(), 0, typedResult, 0, result.Count);
return typedResult;
}