Get enum from enum attribute

2019-01-03 06:32发布

I've got

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

with

public class StringValueAttribute : Attribute
{
    private string _value;

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

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

And I would like to put the value from the item I selected of a combobox into a int:

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

Is this possible, and if so, how? (the StringValue matches the value selected from the combobox).

6条回答
何必那么认真
2楼-- · 2019-01-03 07:00

To parse a string value based on attribute values applied to enum members I'd recommend you use my Enums.NET open source library.

For a custom attribute like the StringValueAttribute you would do this.

Register and store a custom EnumFormat for StringValueAttribute.Value.

Format = Enums.RegisterCustomEnumFormat(m => m.Attributes.Get<StringValueAttribute>()?.Value);

Then use the custom EnumFormat.

Als result = Enums.Parse<Als>("Niet beantwoord", Format); // result == Als.NietBeantwoord

If you were instead using a built-in attribute such as the DescriptionAttribute you could just do this.

Als result = Enums.Parse<Als>("Niet beantwoord", EnumFormat.Description);

In case you're interested, this is how you'd get the string value associated with an enum value.

string value = Als.NietBeantwoord.AsString(Format); // value == "Niet beantwoord"
查看更多
三岁会撩人
3楼-- · 2019-01-03 07:01

I'm using the DescriptionAttribute from Microsoft and the following extension method:

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;
}
查看更多
家丑人穷心不美
4楼-- · 2019-01-03 07:05

Not sure if I am missing something here, can you not do this,

Als temp = (Als)combo1.SelectedItem;
int t = (int)temp;
查看更多
走好不送
5楼-- · 2019-01-03 07:11

Coming here from duplicate links of this highly upvoted question and answer, here is a method that works with C# 7.3's new Enum type constraint. Note that you also need to specify that it is also a struct so that you can make it the nullable TEnum? or else you will get an error.

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;
}
查看更多
Anthone
6楼-- · 2019-01-03 07:19

Here are a couple extension methods that I use for this exact purpose, I've rewritten these to use your StringValueAttribute, but like Oliver I use the DescriptionAttribute in my code.

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

This can be made slightly more simple in .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);
    }

And to call it, just do the following:

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

Conversely, here's a function to get the string from an enum value:

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

And to call it:

string description = Als.NietBeantwoord.StringValue()
查看更多
混吃等死
7楼-- · 2019-01-03 07:20

Here's a helper method that should point you in the right direction.

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

And to call it, just do the following:

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

This probably isn't the best solution though as it's tied to Als and you'll probably want to make this code re-usable. What you'll probably want to strip out the code from my solution to return you the attribute value and then just use Enum.Parse as you are doing in your question.

查看更多
登录 后发表回答