如何通过描述获取枚举值?

4

我有一个枚举类型,代表系统中所有物料组装代码:

public enum EAssemblyUnit
{
    [Description("UCAL1")]
    eUCAL1,
    [Description("UCAL1-3CP")]
    eUCAL13CP,
    [Description("UCAL40-3CP")]
    eUCAL403CP, // ...
}

在系统的另一个部分中,我有被标记为与枚举描述相匹配的字符串的对象。如果给定其中一个字符串,最简洁的方法是什么来获取枚举值?我想象中的解决方案如下:

public EAssemblyUnit FromDescription(string AU)
{
    EAssemblyUnit eAU = <value we find with description matching AU>
    return eAU;
}
3个回答

8
你需要遍历枚举类型的所有静态字段(这是反射存储它们的方式),找到每个字段的Description属性...当你找到正确的时候,获取该字段的值。
例如:
public static T GetValue<T>(string description)
{
    foreach (var field in typeof(T).GetFields())
    {
        var descriptions = (DescriptionAttribute[]) 
               field.GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (descriptions.Any(x => x.Description == description))
        {
            return (T) field.GetValue(null);
        }
    }
    throw new SomeException("Description not found");
}

这是通用的代码,可以重复使用在不同的枚举类型中。

如果你需要经常进行此操作,显然你会希望缓存描述信息,例如:

public static class DescriptionDictionary<T> where T : struct
{
    private static readonly Dictionary<string, T> Map = 
        new Dictionary<string, T>();

    static DescriptionDictionary()
    {
        if (typeof(T).BaseType != typeof(Enum))
        {
            throw new ArgumentException("Must only use with enums");
        }
        // Could do this with a LINQ query, admittedly...
        foreach (var field in typeof(T).GetFields
                 (BindingFlags.Public | BindingFlags.Static))
        {
            T value = (T) field.GetValue(null);
            foreach (var description in (DescriptionAttribute[]) 
               field.GetCustomAttributes(typeof(DescriptionAttribute), false))
            {
                // TODO: Decide what to do if a description comes up
                // more than once
                Map[description.Description] = value;
            }
        }
    }

    public static T GetValue(string description)
    {
        T ret;
        if (Map.TryGetValue(description, out ret))
        {
            return ret;
        }
        throw new WhateverException("Description not found");
    }
}

1
唉,我真的希望有一个“这是一个方便的函数,就像一个描述和值之间的Dictionary<>”。也许我会构建一个静态地保存该字典的类,并在第一次需要时填充它...? - Chuck Wilbur
是的 - 你需要的核心部分是我回答中给出的描述。哦,算了吧...我现在就写。等一下 :) - Jon Skeet
没错,这正是我所想的,但如果能用Jon Skeet在5分钟内写出的代码代替我自己写一个小时的代码,我会非常高兴。经过测试,它的效果非常好。 - Chuck Wilbur
顺便说一句,我读完那个课程之后学到了两三个关于C#的新知识。 - Chuck Wilbur

0
public EAssemblyUnit FromDescription(string AU)
{
    EAssemblyUnit eAU = Enum.Parse(typeof(EAssemblyUnit), AU, true);
    return eAU;
}

3
这样就可以完成对名称的操作,但不包括描述属性。 - Jon Skeet
4
下次我一定会搞定你,Jon Skeet!握紧小拳头对着云彩晃动 - Chris McCall

0

你也可以使用Humanizer来实现。要获取描述,可以使用以下代码:

EAssemblyUnit.eUCAL1.Humanize();

要从描述中获取枚举,您可以使用以下方法

"UCAL1".DehumanizeTo<EAssemblyUnit>();

声明:我是Humanizer的创建者。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接