2010-05-07 14 views
30

TengoGet enumeración de atributos enumeración

public enum Als 
{ 
    [StringValue("Beantwoord")] Beantwoord = 0, 
    [StringValue("Niet beantwoord")] NietBeantwoord = 1, 
    [StringValue("Geselecteerd")] Geselecteerd = 2, 
    [StringValue("Niet geselecteerd")] NietGeselecteerd = 3, 
} 

con

public class StringValueAttribute : Attribute 
{ 
    private string _value; 

    public StringValueAttribute(string value) 
    { 
     _value = value; 
    } 

    public string Value 
    { 
     get { return _value; } 
    } 
} 

Y me gustaría poner el valor del elemento que he seleccionado de un cuadro combinado en un int:

int i = (int)(Als)Enum.Parse(typeof(Als), (string)cboAls.SelectedValue); //<- WRONG 

Esto es posible, y si es así, ¿cómo? (el StringValue coincide con el valor seleccionado del cuadro combinado).

+2

que debería funcionar. ¿Cuál es el problema? –

+1

Consejo aleatorio: puede usar propiedades automáticas para esto. use "public string Value {get; private set;} y puede evitar la variable tacky _value. – Rubys

+0

@Kent Boogaart:" Niet beantwoord "! =" NietBeantwoord " – bniwredyc

Respuesta

19

Aquí hay un método de ayuda que debe apuntar en la dirección correcta.

protected Als GetEnumByStringValueAttribute(string value) 
{ 
    Type enumType = typeof(Als); 
    foreach (Enum val in Enum.GetValues(enumType)) 
    { 
     FieldInfo fi = enumType.GetField(val.ToString()); 
     StringValueAttribute[] attributes = (StringValueAttribute[])fi.GetCustomAttributes(
      typeof(StringValueAttribute), false); 
     StringValueAttribute attr = attributes[0]; 
     if (attr.Value == value) 
     { 
      return (Als)val; 
     } 
    } 
    throw new ArgumentException("The value '" + value + "' is not supported."); 
} 

Y llamarlo, simplemente hacer lo siguiente:

Als result = this.GetEnumByStringValueAttribute<Als>(ComboBox.SelectedValue); 

Esto probablemente no es la mejor solución, ya que aunque está ligado a Als y usted probablemente querrá hacer de este código de re- usable. Lo que probablemente quiera es quitar el código de mi solución para devolverle el valor del atributo y luego simplemente usar Enum.Parse como lo hace en su pregunta.

+8

Esta solución se puede cambiar fácilmente para que sea genérica. Simplemente cambie todas las ocurrencias de 'Als' a' T' y agregue un argumento de tipo llamado 'T' al método. –

+1

salvarme día, gracias por todo hermano. – caras

+0

@DanielHilgarth Intenté hacerlo pero recibí un error que decía '" El parámetro tipo no puede usarse con el operador 'como' porque no tiene una restricción de tipo de clase ni una restricción 'clase' '' en la línea de retorno del método . ¿Tendría un ejemplo práctico de cómo esto podría ser resuelto? –

11

estoy usando el DescriptionAttribute de Microsoft y el siguiente método de extensión:

public static string GetDescription(this Enum value) 
{ 
    if (value == null) 
    { 
     throw new ArgumentNullException("value"); 
    } 

    string description = value.ToString(); 
    FieldInfo fieldInfo = value.GetType().GetField(description); 
    DescriptionAttribute[] attributes = 
     (DescriptionAttribute[]) 
    fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 

    if (attributes != null && attributes.Length > 0) 
    { 
     description = attributes[0].Description; 
    } 
    return description; 
} 
+7

Enfrente de lo que OP pidió ya que quiere enum de cadena y no de cadena de enum, pero eso me ayudó mucho, ¡gracias! – psycho

0

No estoy seguro si estoy perdiendo algo, puede no hacerlo,

Als temp = (Als)combo1.SelectedItem; 
int t = (int)temp; 
5

Aquí están métodos de extensión de pareja que utilizo para este propósito exacto, los reescribí para usar su StringValueAttribute, pero como Oliver uso el DescriptionAttribute en mi código.

public static T FromEnumStringValue<T>(this string description) where T : struct { 
     Debug.Assert(typeof(T).IsEnum); 

     return (T)typeof(T) 
      .GetFields() 
      .First(f => f.GetCustomAttributes(typeof(StringValueAttribute), false) 
         .Cast<StringValueAttribute>() 
         .Any(a => a.Value.Equals(description, StringComparison.OrdinalIgnoreCase)) 
      ) 
      .GetValue(null); 
    } 

Esto se puede hacer un poco más simple en .NET 4.5:

public static T FromEnumStringValue<T>(this string description) where T : struct { 
     Debug.Assert(typeof(T).IsEnum); 

     return (T)typeof(T) 
      .GetFields() 
      .First(f => f.GetCustomAttributes<StringValueAttribute>() 
         .Any(a => a.Value.Equals(description, StringComparison.OrdinalIgnoreCase)) 
      ) 
      .GetValue(null); 
    } 

Y llamarlo, simplemente hacer lo siguiente:

Als result = ComboBox.SelectedValue.FromEnumStringValue<Als>(); 

contrario, aquí es una función para obtener la cadena de un valor enum:

public static string StringValue(this Enum enumItem) { 
     return enumItem 
      .GetType() 
      .GetField(enumItem.ToString()) 
      .GetCustomAttributes<StringValueAttribute>() 
      .Select(a => a.Value) 
      .FirstOrDefault() ?? enumItem.ToString(); 
    } 

Y llamarlo:

string description = Als.NietBeantwoord.StringValue() 
Cuestiones relacionadas