【问题标题】:How can I get an enum value from its description?如何从其描述中获取枚举值?
【发布时间】:2009-06-23 15:20:01
【问题描述】:

我有一个枚举代表系统中的所有材料汇编代码:

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

【问题讨论】:

    标签: c# enums


    【解决方案1】:

    您需要遍历枚举的所有静态字段(这就是它们在反射中的存储方式),为每个字段找到 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");
        }
    }
    

    【讨论】:

    • 呃,真的很希望“这是一个方便的函数,它的作用类似于描述和值之间的字典”。也许我会构建一个类来静态保存该字典并在第一次需要它时填充它......?
    • 是的 - 您需要的核心部分是我给出描述的答案。哦,东西……我现在就写。等一下:)
    • 是的,我就是这么想的,但我很乐意在 5 分钟内完成 Jon Skeet 编写的代码,而不是我自己可能需要一个小时编写的代码。经测试。像魅力一样工作。
    • P.S.哎呀,我学到了 2 或 3 个关于 C# 的新东西,我不知道只是读那门课。
    【解决方案2】:
    public EAssemblyUnit FromDescription(string AU)
    {
        EAssemblyUnit eAU = Enum.Parse(typeof(EAssemblyUnit), AU, true);
        return eAU;
    }
    

    【讨论】:

    • 这将为 name 而不是 description 属性。
    • 下次我会找你的,乔恩·斯基特! 对着云挥动小拳头
    【解决方案3】:

    您也可以为此使用Humanizer。要获取描述,您可以使用:

    EAssemblyUnit.eUCAL1.Humanize();
    

    并从描述中获取枚举,您可以使用

    "UCAL1".DehumanizeTo<EAssemblyUnit>();
    

    免责声明:我是 Humanizer 的创造者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 1970-01-01
      相关资源
      最近更新 更多