Bạn có thể xác định một phương pháp mở rộng hữu ích ...
Type type = typeof(ProjectController);
var attributes = type.GetCustomAttributes<CustomDescriptionAttribute>(true);
Dưới đây là phương pháp mở rộng:
/// <summary>Searches and returns attributes. The inheritance chain is not used to find the attributes.</summary>
/// <typeparam name="T">The type of attribute to search for.</typeparam>
/// <param name="type">The type which is searched for the attributes.</param>
/// <returns>Returns all attributes.</returns>
public static T[] GetCustomAttributes<T>(this Type type) where T : Attribute
{
return GetCustomAttributes(type, typeof(T), false).Select(arg => (T)arg).ToArray();
}
/// <summary>Searches and returns attributes.</summary>
/// <typeparam name="T">The type of attribute to search for.</typeparam>
/// <param name="type">The type which is searched for the attributes.</param>
/// <param name="inherit">Specifies whether to search this member's inheritance chain to find the attributes. Interfaces will be searched, too.</param>
/// <returns>Returns all attributes.</returns>
public static T[] GetCustomAttributes<T>(this Type type, bool inherit) where T : Attribute
{
return GetCustomAttributes(type, typeof(T), inherit).Select(arg => (T)arg).ToArray();
}
/// <summary>Private helper for searching attributes.</summary>
/// <param name="type">The type which is searched for the attribute.</param>
/// <param name="attributeType">The type of attribute to search for.</param>
/// <param name="inherit">Specifies whether to search this member's inheritance chain to find the attribute. Interfaces will be searched, too.</param>
/// <returns>An array that contains all the custom attributes, or an array with zero elements if no attributes are defined.</returns>
private static object[] GetCustomAttributes(Type type, Type attributeType, bool inherit)
{
if(!inherit)
{
return type.GetCustomAttributes(attributeType, false);
}
var attributeCollection = new Collection<object>();
var baseType = type;
do
{
baseType.GetCustomAttributes(attributeType, true).Apply(attributeCollection.Add);
baseType = baseType.BaseType;
}
while(baseType != null);
foreach(var interfaceType in type.GetInterfaces())
{
GetCustomAttributes(interfaceType, attributeType, true).Apply(attributeCollection.Add);
}
var attributeArray = new object[attributeCollection.Count];
attributeCollection.CopyTo(attributeArray, 0);
return attributeArray;
}
/// <summary>Applies a function to every element of the list.</summary>
private static void Apply<T>(this IEnumerable<T> enumerable, Action<T> function)
{
foreach(var item in enumerable)
{
function.Invoke(item);
}
}
Cập nhật:
Đây là một phiên bản ngắn hơn theo đề nghị của SimonD trong một chú thích:
private static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this Type type)
{
var attributeType = typeof(T);
return type.GetCustomAttributes(attributeType, true).
Union(type.GetInterfaces().
SelectMany(interfaceType => interfaceType.GetCustomAttributes(attributeType, true))).
Distinct().Cast<T>();
}
Bạn có chắc chắn về điều này không? Phương thức MemberInfo.GetCustomAttributes lấy một đối số cho biết liệu cây kế thừa có nên được tìm kiếm hay không. –
Hmm. Tôi chỉ nhận thấy rằng câu hỏi là về các thuộc tính kế thừa từ một giao diện không phải từ một lớp cơ sở. –
Có lý do gì để đặt thuộc tính trên giao diện không? –