Наследование пользовательских атрибутов по абстрактным свойствам
У меня есть пользовательский атрибут, который я хочу применить к базовому абстрактному классу, чтобы я мог пропускать элементы, которые не нужно просматривать пользователю при отображении элемента в HTML. Кажется, что свойства, переопределяющие базовый класс, не наследуют атрибуты.
Заменяет ли базовые свойства (абстрактные или виртуальные) атрибуты, отнесенные к исходному свойству?
От класса атрибута Defination
[AttributeUsage(AttributeTargets.Property,
Inherited = true,
AllowMultiple = false)]
public class NoHtmlOutput : Attribute
{
}
От абстрактного класса Defination
[NoHtmlOutput]
public abstract Guid UniqueID { get; set; }
От определения класса бетона
public override Guid UniqueID{ get{ return MasterId;} set{MasterId = value;}}
От проверки класса для атрибута
Type t = o.GetType();
foreach (PropertyInfo pi in t.GetProperties())
{
if (pi.GetCustomAttributes(typeof(NoHtmlOutput), true).Length == 1)
continue;
// processing logic goes here
}
Ответы
Ответ 1
Нет, атрибуты наследуются.
Это метод GetCustomAttributes()
, который не рассматривает родительские объявления. Он рассматривает только атрибуты, применяемые к указанному элементу. Из документов:
Примечание
Этот метод игнорирует наследование параметр для свойств и событий. Поиск цепочки наследования для атрибуты свойств и событий, используйте соответствующие перегрузки Атрибут..::. GetCustomAttributes Метод.
Ответ 2
Вместо вызова PropertyInfo.GetCustomAttributes(...) вы должны вызвать статический метод System.Attribute.GetCustomAttributes(pi,...), как в:
PropertyInfo info = GetType().GetProperties();
// this gets only the attributes in the derived class and ignores the 'true' parameter
object[] DerivedAttributes = info.GetCustomAttributes(typeof(MyAttribute),true);
// this gets all of the attributes up the heirarchy
object[] InheritedAttributes = System.Attribute.GetCustomAttributes(info,typeof(MyAttribute),true);
Ответ 3
Похоже, что это происходит только тогда, когда метод переопределения также имеет атрибут.
http://msdn.microsoft.com/en-us/library/a19191fh.aspx
Однако вы можете переопределить атрибуты того же типа или применить дополнительные атрибуты к производному компоненту. Следующий фрагмент кода показывает настраиваемый элемент управления, который переопределяет свойство Text, унаследованное от элемента управления, путем переопределения атрибута BrowsableAttribute, применяемого в базовом классе.
Visual Basic
Public Class MyControl
Inherits Control
' The base class has [Browsable(true)] applied to the Text property.
<Browsable(False)> _
Public Overrides Property [Text]() As String
...
End Property
...
End Class
Ответ 4
Вот моя попытка. Это метод расширения на MemberInfo
, который вручную поднимает иерархию наследования. Это похоже на совместимость с динамическими прокси-серверами... по крайней мере, шлангом, созданным Castle, так что я предполагаю, что он будет совместим с любой прокси-библиотекой.
public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo instance)
{
while (instance != null)
{
object[] attributes = instance.GetCustomAttributes(typeof(T), false);
if (attributes.Length > 0)
{
return attributes.Cast<T>();
}
Type ancestor = instance.DeclaringType.BaseType;
if (ancestor != null)
{
IEnumerable<MemberInfo> ancestormatches = ancestor.FindMembers(instance.MemberType, BindingFlags.Instance | BindingFlags.Public,
(m, s) =>
{
return m.Name == (string)s;
}, instance.Name);
instance = ancestormatches.FirstOrDefault();
}
else
{
instance = null;
}
}
return new T[] { };
}
И вы бы использовали его вот так.
Type t = o.GetType();
foreach (PropertyInfo pi in t.GetProperties())
{
IEnumerable<NoHtmlOutput> attributes = pi.GetCustomAttributes<NoHtmlOutput>();
foreach (NoHtmlOutput attribute in attributes)
{
Console.WriteLine(attribute);
}
}
Ответ 5
Вы можете использовать
PropertyInfo::GetCustomAttributes<T>(true)
который отлично работает, см. пример:
https://dotnetfiddle.net/2IhEWH
поэтому нет необходимости использовать статический метод
System.Attribute.GetCustomAttributes