2010-03-25 15 views
38

Tengo un atributo personalizado que quiero aplicar a mi base de clase abstracta para que pueda saltar elementos que no deben ser vistos por el usuario cuando se muestra el elemento en HTML . Parece que las propiedades que reemplazan a la clase base no heredan los atributos.Herencia de atributos personalizados en propiedades abstractas

¿El propiedades básicas primordiales (abstracta o virtual) soplar atributos colocados en la propiedad original?

De Defination clase Atributo

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

De Resumen Clase Defination

[NoHtmlOutput] 
public abstract Guid UniqueID { get; set; } 

De Defination clase concreta

public override Guid UniqueID{ get{ return MasterId;} set{MasterId = value;}} 

de la clase comprobación de atributo

 Type t = o.GetType(); 
     foreach (PropertyInfo pi in t.GetProperties()) 
     { 
      if (pi.GetCustomAttributes(typeof(NoHtmlOutput), true).Length == 1) 
       continue; 
      // processing logic goes here 
     } 

Respuesta

25

No, atributos son heredados.

Es el método más GetCustomAttributes() que no se ve en las declaraciones de los padres. Solo mira los atributos aplicados al miembro especificado. From the docs:

Remarks

Este método ignora el parámetro hereda para las propiedades y eventos. Para buscar en la cadena de herencia de los atributos en propiedades y eventos, utilice las sobrecargas apropiadas del método Atributo .. ::. GetCustomAttributes .

+0

Buscando en la cadena de proporcionando el parámetro heredado pi.GetCustomAttributes (typeof (NoHtmlOutp) ut), verdadero) –

+0

Lea los comentarios. PropertyInfo.GetCustomAttributes() * ignora * el parámetro heredado. – womp

+2

No importa ... Microsoft tuvo que ponerlo en la cara de tipo más pequeña posible –

0

Parece que solo ocurre cuando el método de anulación también tiene el atributo.

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

Sin embargo, puede anular los atributos del mismo tipo o aplicar atributos adicionales para el componente derivado. El fragmento de código siguiente muestra un control personalizado que reemplaza la propiedad de texto se hereda de Control reemplazando el atributo BrowsableAttribute aplicada en la clase base. 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 
55

En lugar de llamar PropertyInfo.GetCustomAttributes (...), hay que llamar a los System.Attribute.GetCustomAttributes método estático (pi, ...), como en:

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); 
+1

Esta debería ser la respuesta. Cambiar de 'mytype.GetCustomAttributes()' a 'System.Attribute.GetCustomAttribute()' hace que el parámetro 'inherit' funcione como se supone que debe hacerlo. ¡Magia! – nathanchere

+2

No funciona para mí en .NET 4.6.1. Intentando obtener el atributo de la clase POCO de un proxy dinámico de Entity Framework (cuyo tipo base es la clase POCO). – AyCabron

+0

Tiene que ser un Atributo personalizado. Algo como 'DataMemberAttribute' no aparecerá en la lista. – lordcheeto

0

Aquí está mi intento. Este es un método de extensión en MemberInfo que sube manualmente la jerarquía de herencia. Esto parece ser compatible con los proxies dinámicos ... al menos la manguera creado por el castillo de todos modos así que estoy asumiendo que sería compatible con cualquier biblioteca de proxy.

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[] { }; 
} 

Y lo usaría así.

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

Puede utilizar

PropertyInfo::GetCustomAttributes<T>(true) 

que funciona muy bien, véase el ejemplo: https://dotnetfiddle.net/2IhEWH

es así, no hay necesidad de utilizar el método estático

System.Attribute.GetCustomAttributes 
Cuestiones relacionadas