2011-02-23 10 views
28

Tengo una enumeración en la que cada miembro tiene un atributo personalizado aplicado. ¿Cómo puedo recuperar el valor almacenado en cada atributo?¿Cómo obtener valores de atributos personalizados para enums?

Ahora mismo esto:

var attributes = typeof (EffectType).GetCustomAttributes (false); 
foreach (object attribute in attributes) 
{ 
    GPUShaderAttribute attr = (GPUShaderAttribute) attribute; 
    if (attr != null) 
     return attr.GPUShader; 
} 
return 0; 

Otra cuestión es, si no se encuentra, lo que si regreso? 0 es implcity convertible a cualquier enumeración, ¿verdad? Es por eso que devolví eso.

Olvidé mencionar que el código anterior devuelve 0 para cada miembro enum.

+1

posible duplicado de [Lo AttributeTarget debo usar para los miembros de enumeración?] (Http: // stackoverflow .com/questions/5032774/what-attributetarget-should-i-use-for-enum-members) –

+2

No, esto es diferente. Aquí estoy tratando de obtener los atributos personalizados establecidos en un miembro enum que usa la reflexión. –

+1

posible duplicado de [Obtener atributos del valor de Enum] (http://stackoverflow.com/questions/1799370/getting-attributes-of-enums-value) –

Respuesta

26

Es un poco desordenado para hacer lo que usted está tratando de hacer lo que usted tiene que utilizar la reflexión:

public GPUShaderAttribute GetGPUShader(EffectType effectType) 
{ 
    MemberInfo memberInfo = typeof(EffectType).GetMember(effectType.ToString()) 
               .FirstOrDefault(); 

    if (memberInfo != null) 
    { 
     GPUShaderAttribute attribute = (GPUShaderAttribute) 
        memberInfo.GetCustomAttributes(typeof(GPUShaderAttribute), false) 
           .FirstOrDefault(); 
     return attribute; 
    } 

    return null; 
} 

Esto devolverá una instancia de la GPUShaderAttribute que es relevante para el marcado en el valor de enumeración de EffectType. Tienes que llamar en un valor específico de la EffectType enumeración:

GPUShaderAttribute attribute = GetGPUShader(EffectType.MyEffect); 

Una vez que tenga la instancia del atributo, puede obtener los valores específicos de ella que están marcados en marcha en los valores de enumeración individuales.

+0

Gracias, hombre, funciona. No sabía que sería tan complicado. Pero esta es la forma más simple, ¿verdad? También sabes por qué mi versión no funcionó. Pensé que dado que las enumeraciones no pueden ser instanciadas, el uso de enum.getCustomAttributes funcionaría. –

+1

@Joan: Esta es la forma más sencilla que yo sepa. Su método no funcionó ya que obtenía los atributos definidos en el tipo de enumeración en lugar de los valores del tipo. – adrianbanks

+0

Gracias Adrian, eso tiene sentido ahora. –

22

Hay otro método para hacer esto con los genéricos:

public static T GetAttribute<T>(Enum enumValue) where T: Attribute 
{ 
    T attribute; 

    MemberInfo memberInfo = enumValue.GetType().GetMember(enumValue.ToString()) 
            .FirstOrDefault(); 

    if (memberInfo != null) 
    { 
     attribute = (T) memberInfo.GetCustomAttributes(typeof (T), false).FirstOrDefault(); 
     return attribute; 
    } 
    return null; 
} 
+1

Me gusta esto, pero no se tiene en cuenta la posibilidad de tener varias instancias del mismo atributo. Tomé lo que tenía y lo modifiqué para usar T [] en lugar de T, luego eliminé FirstOrDefault() en GetCustomAttributes. –

15

trate de usar un método genérico

Atributo:

class DayAttribute : Attribute 
{ 
    public string Name { get; private set; } 

    public DayAttribute(string name) 
    { 
     this.Name = name; 
    } 
} 

Enum:

enum Days 
{ 
    [Day("Saturday")] 
    Sat, 
    [Day("Sunday")] 
    Sun, 
    [Day("Monday")] 
    Mon, 
    [Day("Tuesday")] 
    Tue, 
    [Day("Wednesday")] 
    Wed, 
    [Day("Thursday")] 
    Thu, 
    [Day("Friday")] 
    Fri 
} 

método genérico :

 public static TAttribute GetAttribute<TAttribute>(this Enum value) 
     where TAttribute : Attribute 
    { 
     var enumType = value.GetType(); 
     var name = Enum.GetName(enumType, value); 
     return enumType.GetField(name).GetCustomAttributes(false).OfType<TAttribute>().SingleOrDefault(); 
    } 

invocación:

 static void Main(string[] args) 
    { 
     var day = Days.Mon; 
     Console.WriteLine(day.GetAttribute<DayAttribute>().Name); 
     Console.ReadLine(); 
    } 

Resultado:

Lunes

+0

¡Ojalá pudiera votar esta respuesta 100 veces! Buena cosa :-) – Gericke

Cuestiones relacionadas