Get Enum from Description attribute [duplicate]

2018-12-31 17:45发布

问题:

Possible Duplicate:
Finding an enum value by its Description Attribute

I have a generic extension method which gets the Description attribute from an Enum:

enum Animal
{
    [Description(\"\")]
    NotSet = 0,

    [Description(\"Giant Panda\")]
    GiantPanda = 1,

    [Description(\"Lesser Spotted Anteater\")]
    LesserSpottedAnteater = 2
}

public static string GetDescription(this Enum value)
{            
    FieldInfo field = value.GetType().GetField(value.ToString());

    DescriptionAttribute attribute
            = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
                as DescriptionAttribute;

    return attribute == null ? value.ToString() : attribute.Description;
}

so I can do...

string myAnimal = Animal.GiantPanda.GetDescription(); // = \"Giant Panda\"

now, I\'m trying to work out the equivalent function in the other direction, something like...

Animal a = (Animal)Enum.GetValueFromDescription(\"Giant Panda\", typeof(Animal));

回答1:

public static class EnumEx
{
    public static T GetValueFromDescription<T>(string description)
    {
        var type = typeof(T);
        if(!type.IsEnum) throw new InvalidOperationException();
        foreach(var field in type.GetFields())
        {
            var attribute = Attribute.GetCustomAttribute(field,
                typeof(DescriptionAttribute)) as DescriptionAttribute;
            if(attribute != null)
            {
                if(attribute.Description == description)
                    return (T)field.GetValue(null);
            }
            else
            {
                if(field.Name == description)
                    return (T)field.GetValue(null);
            }
        }
        throw new ArgumentException(\"Not found.\", \"description\");
        // or return default(T);
    }
}

Usage:

var panda = EnumEx.GetValueFromDescription<Animal>(\"Giant Panda\");


回答2:

rather than extension methods, just try a couple of static methods

public static class Utility
{
    public static string GetDescriptionFromEnumValue(Enum value)
    {
        DescriptionAttribute attribute = value.GetType()
            .GetField(value.ToString())
            .GetCustomAttributes(typeof (DescriptionAttribute), false)
            .SingleOrDefault() as DescriptionAttribute;
        return attribute == null ? value.ToString() : attribute.Description;
    }

    public static T GetEnumValueFromDescription<T>(string description)
    {
        var type = typeof(T);
        if (!type.IsEnum)
            throw new ArgumentException();
        FieldInfo[] fields = type.GetFields();
        var field = fields
                        .SelectMany(f => f.GetCustomAttributes(
                            typeof(DescriptionAttribute), false), (
                                f, a) => new { Field = f, Att = a })
                        .Where(a => ((DescriptionAttribute)a.Att)
                            .Description == description).SingleOrDefault();
        return field == null ? default(T) : (T)field.Field.GetRawConstantValue();
    }
}

and use here

var result1 = Utility.GetDescriptionFromEnumValue(
    Animal.GiantPanda);
var result2 = Utility.GetEnumValueFromDescription<Animal>(
    \"Lesser Spotted Anteater\");


回答3:

The solution works good except if you have a Web Service.

You would need to do the Following as the Description Attribute is not serializable.

[DataContract]
public enum ControlSelectionType
{
    [EnumMember(Value = \"Not Applicable\")]
    NotApplicable = 1,
    [EnumMember(Value = \"Single Select Radio Buttons\")]
    SingleSelectRadioButtons = 2,
    [EnumMember(Value = \"Completely Different Display Text\")]
    SingleSelectDropDownList = 3,
}

public static string GetDescriptionFromEnumValue(Enum value)
{
        EnumMemberAttribute attribute = value.GetType()
            .GetField(value.ToString())
            .GetCustomAttributes(typeof(EnumMemberAttribute), false)
            .SingleOrDefault() as EnumMemberAttribute;
        return attribute == null ? value.ToString() : attribute.Value;
}


回答4:

Should be pretty straightforward, its just the reverse of your previous method;

public static int GetEnumFromDescription(string description, Type enumType)
{
    foreach (var field in enumType.GetFields())
    {
        DescriptionAttribute attribute
            = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))as DescriptionAttribute;
        if(attribute == null)
            continue;
        if(attribute.Description == description)
        {
            return (int) field.GetValue(null);
        }
    }
    return 0;
}

Usage:

Console.WriteLine((Animal)GetEnumFromDescription(\"Giant Panda\",typeof(Animal)));


回答5:

You can\'t extend Enum as it\'s a static class. You can only extend instances of a type. With this in mind, you\'re going to have to create a static method yourself to do this; the following should work when combined with your existing method GetDescription:

public static class EnumHelper
{
    public static T GetEnumFromString<T>(string value)
    {
        if (Enum.IsDefined(typeof(T), value))
        {
            return (T)Enum.Parse(typeof(T), value, true);
        }
        else
        {
            string[] enumNames = Enum.GetNames(typeof(T));
            foreach (string enumName in enumNames)
            {  
                object e = Enum.Parse(typeof(T), enumName);
                if (value == GetDescription((Enum)e))
                {
                    return (T)e;
                }
            }
        }
        throw new ArgumentException(\"The value \'\" + value 
            + \"\' does not match a valid enum name or description.\");
    }
}

And the usage of it would be something like this:

Animal giantPanda = EnumHelper.GetEnumFromString<Animal>(\"Giant Panda\");


回答6:

You need to iterate through all the enum values in Animal and return the value that matches the description you need.