Наследование пользовательских атрибутов в абстрактных свойствах - PullRequest
44 голосов
/ 26 марта 2010

У меня есть собственный атрибут, который я хочу применить к своему базовому абстрактному классу, чтобы я мог пропускать элементы, которые не нужно просматривать пользователю при отображении элемента в HTML. Кажется, что свойства, переопределяющие базовый класс, не наследуют атрибуты.

Превышают ли базовые свойства (абстрактные или виртуальные) атрибуты, помещенные в исходное свойство?

Из класса атрибутов Определение

[AttributeUsage(AttributeTargets.Property,
                Inherited = true,
                AllowMultiple = false)]
public class NoHtmlOutput : Attribute
{
}

Из определения абстрактного класса

[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
        }

Ответы [ 5 ]

61 голосов
/ 24 августа 2011

Вместо вызова 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);
30 голосов
/ 26 марта 2010

Нет, атрибуты наследуются.

Это метод GetCustomAttributes(), который не смотрит на родительские объявления. Он только смотрит на атрибуты, примененные к указанному члену. Из документов :

Примечания

Этот метод игнорирует наследование параметр для свойств и событий. Для поиска цепочки наследования для атрибуты на свойства и события, использовать соответствующие перегрузки Атрибут .. ::. GetCustomAttributes способ.

0 голосов
/ 01 декабря 2016

Вы можете использовать

PropertyInfo::GetCustomAttributes<T>(true)

, который работает нормально, см. Пример: https://dotnetfiddle.net/2IhEWH

Итак, нет необходимости использовать статический метод

System.Attribute.GetCustomAttributes
0 голосов
/ 09 ноября 2016

Вот моя попытка. Это метод расширения в 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);
    }
}
0 голосов
/ 26 марта 2010

Похоже, это происходит только тогда, когда переопределяющий метод также имеет атрибут.

http://msdn.microsoft.com/en-us/library/a19191fh.aspx

Однако вы можете переопределить атрибуты того же типа или применить дополнительные атрибуты к производному компоненту. В следующем фрагменте кода показан пользовательский элемент управления, который переопределяет свойство Text, унаследованное от Control, путем переопределения атрибута 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
...