Pobierz enum z atrybutu enum

Mam

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

Z

public class StringValueAttribute : Attribute
{
    private string _value;

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

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

I chciałbym umieścić wartość z elementu, który wybrałem z comboboxu W int:

int i = (int)(Als)Enum.Parse(typeof(Als), (string)cboAls.SelectedValue); //<- WRONG
Czy jest to możliwe, a jeśli tak, to w jaki sposób? (StringValue odpowiada wartości wybranej z comboboxu).
Author: nawfal, 2010-05-07

5 answers

Oto metoda pomocnicza, która powinna wskazać ci właściwy kierunek.

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.");
}

I aby to nazwać, po prostu wykonaj następujące czynności:

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

To prawdopodobnie nie jest najlepsze rozwiązanie, ponieważ jest powiązane z Als i prawdopodobnie będziesz chciał, aby ten kod mógł być ponownie użyty. Prawdopodobnie będziesz chciał usunąć kod z mojego rozwiązania, aby zwrócić Ci wartość atrybutu, a następnie po prostu użyć Enum.Parse, jak robisz w swoim pytaniu.

 20
Author: GenericTypeTea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-10 05:11:39

Używam DescriptionAttribute firmy Microsoft i następującej metody rozszerzenia:

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;
}
 11
Author: Oliver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-07 09:42:48

Oto kilka metod rozszerzeń, których używam w tym właśnie celu, przepisałem je tak, aby używały twojego StringValueAttribute, ale podobnie jak Oliver używamDescriptionAttribute w moim kodzie.

    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);
    }
Można to nieco uprościć w. 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);
    }

I aby to nazwać, po prostu wykonaj następujące czynności:

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

Natomiast , Oto funkcja, która pobiera łańcuch z wartości enum:

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

I nazwać go:

string description = Als.NietBeantwoord.StringValue()
 6
Author: joshperry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:23

Nie jestem pewien, czy coś mi tu umyka, czy możesz tego nie robić,

Als temp = (Als)combo1.SelectedItem;
int t = (int)temp;
 0
Author: theraneman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-07 09:45:57

Idąc tutaj z duplikatów linków to wysoce upvoted pytanie i ODPOWIEDŹ, Oto metoda, która działa z nowym ograniczeniem typu Enum W C# 7.3. Zauważ, że musisz również określić, że jest to również struct, aby można było uczynić go nullable TEnum? w przeciwnym razie pojawi się błąd.

public static TEnum? GetEnumFromDescription<TEnum>(string description)
    where TEnum : struct, Enum 
{
    var comparison = StringComparison.OrdinalIgnoreCase;
    foreach (var field in typeof(TEnum).GetFields())
    {
        var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
        if (attribute != null)
        {
            if (string.Compare(attribute.Description, description, comparison) == 0)
                return (TEnum)field.GetValue(null);
        }
        if (string.Compare(field.Name, description, comparison) == 0)
            return (TEnum)field.GetValue(null);
    }
    return null;
}
 0
Author: DLeh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-14 18:31:34