代码之家  ›  专栏  ›  技术社区  ›  Alex K

获取枚举值的属性

  •  414
  • Alex K  · 技术社区  · 15 年前

    我想知道是否可以获取枚举值的属性而不是枚举本身的属性?例如,假设我有以下枚举:

    using System.ComponentModel; // for DescriptionAttribute
    
    enum FunkyAttributesEnum
    {
        [Description("Name With Spaces1")]
        NameWithoutSpaces1,    
        [Description("Name With Spaces2")]
        NameWithoutSpaces2
    }
    

    我想要的是给定枚举类型,生成枚举字符串值的2个元组及其描述。

    价值是容易的:

    Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
    foreach (int value in values)
        Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
    

    但如何获取description属性的值来填充tuple.desc?如果属性属于枚举本身,我可以考虑如何执行它,但是对于如何从枚举的值中获取它,我感到茫然。

    19 回复  |  直到 6 年前
        1
  •  443
  •   Hakan Fıstık MuriloKunze    8 年前

    这应该能满足你的需要。

    var type = typeof(FunkyAttributesEnum);
    var memInfo = type.GetMember(FunkyAttributesEnum.NameWithoutSpaces1.ToString());
    var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
    var description = ((DescriptionAttribute)attributes[0]).Description;
    
        2
  •  237
  •   Karl Glennon    10 年前

    这段代码应该为您提供一个很好的任何枚举的小扩展方法,让您检索一个通用属性。我相信它不同于上面的lambda函数,因为它使用起来更简单,而且稍微有点——您只需要传入泛型类型。

    public static class EnumHelper
    {
        /// <summary>
        /// Gets an attribute on an enum field value
        /// </summary>
        /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
        /// <param name="enumVal">The enum value</param>
        /// <returns>The attribute of type T that exists on the enum value</returns>
        /// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
        public static T GetAttributeOfType<T>(this Enum enumVal) where T:System.Attribute
        {
            var type = enumVal.GetType();
            var memInfo = type.GetMember(enumVal.ToString());
            var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
            return (attributes.Length > 0) ? (T)attributes[0] : null;
        }
    }
    
        3
  •  77
  •   M Reza    7 年前

    这是使用lambda进行选择的通用实现

    public static Expected GetAttributeValue<T, Expected>(this Enum enumeration, Func<T, Expected> expression)
        where T : Attribute
    {
        T attribute =
          enumeration
            .GetType()
            .GetMember(enumeration.ToString())
            .Where(member => member.MemberType == MemberTypes.Field)
            .FirstOrDefault()
            .GetCustomAttributes(typeof(T), false)
            .Cast<T>()
            .SingleOrDefault();
    
        if (attribute == null)
            return default(Expected);
    
        return expression(attribute);
    }
    

    这样称呼它:

    string description = targetLevel.GetAttributeValue<DescriptionAttribute, string>(x => x.Description);
    
        4
  •  50
  •   Troy Alford    6 年前

    我在这里合并了几个答案,以创建一个更具扩展性的解决方案。我提供它只是为了将来对任何人都有帮助。原始过账 here .

    using System;
    using System.ComponentModel;
    
    public static class EnumExtensions {
    
        // This extension method is broken out so you can use a similar pattern with 
        // other MetaData elements in the future. This is your base method for each.
        public static T GetAttribute<T>(this Enum value) where T : Attribute {
            var type = value.GetType();
            var memberInfo = type.GetMember(value.ToString());
            var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
            return attributes.Length > 0 
              ? (T)attributes[0]
              : null;
        }
    
        // This method creates a specific call to the above method, requesting the
        // Description MetaData attribute.
        public static string ToName(this Enum value) {
            var attribute = value.GetAttribute<DescriptionAttribute>();
            return attribute == null ? value.ToString() : attribute.Description;
        }
    
    }
    

    此解决方案在枚举上创建一对扩展方法。第一种方法允许您使用反射来检索与您的值相关联的任何属性。第二个调用专门检索 DescriptionAttribute 然后返回 Description 价值。

    例如,考虑使用 说明属性 属性来自 System.ComponentModel

    using System.ComponentModel;
    
    public enum Days {
        [Description("Sunday")]
        Sun,
        [Description("Monday")]
        Mon,
        [Description("Tuesday")]
        Tue,
        [Description("Wednesday")]
        Wed,
        [Description("Thursday")]
        Thu,
        [Description("Friday")]
        Fri,
        [Description("Saturday")]
        Sat
    }
    

    要使用上述扩展方法,现在只需调用以下内容:

    Console.WriteLine(Days.Mon.ToName());
    

    var day = Days.Mon;
    Console.WriteLine(day.ToName());
    
        5
  •  37
  •   Community CDub    8 年前

    除了 AdamCrawford response ,我还创建了一个更专门的扩展方法,提供它来获取描述。

    public static string GetAttributeDescription(this Enum enumValue)
    {
        var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>();
        return attribute == null ? String.Empty : attribute.Description;
    } 
    

    因此,要获取描述,可以使用原始扩展方法作为

    string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description
    

    或者您可以在这里简单地调用扩展方法,如下所示:

    string desc = myEnumVariable.GetAttributeDescription();
    

    希望能让代码更可读。

        6
  •  12
  •   Aydin    10 年前

    流畅的一行…

    这里我用的是 DisplayAttribute 它包含两个 Name Description 性质。

    public static DisplayAttribute GetDisplayAttributesFrom(this Enum enumValue, Type enumType)
    {
        return enumType.GetMember(enumValue.ToString())
                       .First()
                       .GetCustomAttribute<DisplayAttribute>();
    }
    

    例子

    public enum ModesOfTransport
    {
        [Display(Name = "Driving",    Description = "Driving a car")]        Land,
        [Display(Name = "Flying",     Description = "Flying on a plane")]    Air,
        [Display(Name = "Sea cruise", Description = "Cruising on a dinghy")] Sea
    }
    
    void Main()
    {
        ModesOfTransport TransportMode = ModesOfTransport.Sea;
        DisplayAttribute metadata = TransportMode.GetDisplayAttributesFrom(typeof(ModesOfTransport));
        Console.WriteLine("Name: {0} \nDescription: {1}", metadata.Name, metadata.Description);
    }
    

    产量

    Name: Sea cruise 
    Description: Cruising on a dinghy
    
        7
  •  7
  •   Community CDub    8 年前

    下面是从显示属性获取信息的代码。它使用一个通用方法来检索属性。如果找不到属性,则将枚举值转换为字符串,并将pascal/camel大小写转换为标题大小写(获取的代码 here )

    public static class EnumHelper
    {
        // Get the Name value of the Display attribute if the   
        // enum has one, otherwise use the value converted to title case.  
        public static string GetDisplayName<TEnum>(this TEnum value)
            where TEnum : struct, IConvertible
        {
            var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
            return attr == null ? value.ToString().ToSpacedTitleCase() : attr.Name;
        }
    
        // Get the ShortName value of the Display attribute if the   
        // enum has one, otherwise use the value converted to title case.  
        public static string GetDisplayShortName<TEnum>(this TEnum value)
            where TEnum : struct, IConvertible
        {
            var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
            return attr == null ? value.ToString().ToSpacedTitleCase() : attr.ShortName;
        }
    
        /// <summary>
        /// Gets an attribute on an enum field value
        /// </summary>
        /// <typeparam name="TEnum">The enum type</typeparam>
        /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
        /// <param name="value">The enum value</param>
        /// <returns>The attribute of type T that exists on the enum value</returns>
        private static T GetAttributeOfType<TEnum, T>(this TEnum value)
            where TEnum : struct, IConvertible
            where T : Attribute
        {
    
            return value.GetType()
                        .GetMember(value.ToString())
                        .First()
                        .GetCustomAttributes(false)
                        .OfType<T>()
                        .LastOrDefault();
        }
    }
    

    这是字符串转换为标题大小写的扩展方法:

        /// <summary>
        /// Converts camel case or pascal case to separate words with title case
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToSpacedTitleCase(this string s)
        {
            //https://stackoverflow.com/a/155486/150342
            CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
            TextInfo textInfo = cultureInfo.TextInfo;
            return textInfo
               .ToTitleCase(Regex.Replace(s, 
                            "([a-z](?=[A-Z0-9])|[A-Z](?=[A-Z][a-z]))", "$1 "));
        }
    
        8
  •  4
  •   Jitendra Pancholi    11 年前

    从枚举获取字典。

    public static IDictionary<string, int> ToDictionary(this Type enumType)
    {
        return Enum.GetValues(enumType)
        .Cast<object>()
        .ToDictionary(v => ((Enum)v).ToEnumDescription(), k => (int)k); 
    }
    

    现在这样称呼…

    var dic = typeof(ActivityType).ToDictionary();
    

    EnumDeccription Ext方法

    public static string ToEnumDescription(this Enum en) //ext method
    {
        Type type = en.GetType();
        MemberInfo[] memInfo = type.GetMember(en.ToString());
        if (memInfo != null && memInfo.Length > 0)
        {
            object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (attrs != null && attrs.Length > 0)
                return ((DescriptionAttribute)attrs[0]).Description;
        }
        return en.ToString();
    }
    
    public enum ActivityType
    {
        [Description("Drip Plan Email")]
        DripPlanEmail = 1,
        [Description("Modification")]
        Modification = 2,
        [Description("View")]
        View = 3,
        [Description("E-Alert Sent")]
        EAlertSent = 4,
        [Description("E-Alert View")]
        EAlertView = 5
    }
    
        9
  •  3
  •   Nick N.    12 年前

    我实现了这个扩展方法来从枚举值中获取描述。它适用于所有类型的枚举。

    public static class EnumExtension
    {
        public static string ToDescription(this System.Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
            return attributes.Length > 0 ? attributes[0].Description : value.ToString();
        }
    }
    
        10
  •  3
  •   wonea Ilya Smagin    8 年前

    这是AdamCrawford答案的.NET核心版本,使用 System.Reflection.TypeExtensions ;

    public static class EnumHelper
    {
        /// <summary>
        /// Gets an attribute on an enum field value
        /// </summary>
        /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
        /// <param name="enumVal">The enum value</param>
        /// <returns>The attribute of type T that exists on the enum value</returns>
        /// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
        public static T GetAttributeOfType<T>(this Enum enumVal) where T : System.Attribute
        {
            var type = enumVal.GetType();
            var memInfo = type.GetMember(enumVal.ToString());
            IEnumerable<Attribute> attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
            return (T)attributes?.ToArray()[0];
        }
    }
    
        11
  •  3
  •   HouseCat    8 年前

    添加我的网络框架和网络核心解决方案。

    我将其用于我的网络框架实现:

    public static class EnumerationExtension
    {
        public static string Description( this Enum value )
        {
            // get attributes  
            var field = value.GetType().GetField( value.ToString() );
            var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false );
    
            // return description
            return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found";
        }
    }
    

    这对NetCore不起作用,因此我将其修改为:

    public static class EnumerationExtension
    {
        public static string Description( this Enum value )
        {
            // get attributes  
            var field = value.GetType().GetField( value.ToString() );
            var attributes = field.GetCustomAttributes( false );
    
            // Description is in a hidden Attribute class called DisplayAttribute
            // Not to be confused with DisplayNameAttribute
            dynamic displayAttribute = null;
    
            if (attributes.Any())
            {
                displayAttribute = attributes.ElementAt( 0 );
            }
    
            // return description
            return displayAttribute?.Description ?? "Description Not Found";
        }
    }
    

    枚举示例:

    public enum ExportTypes
    {
        [Display( Name = "csv", Description = "text/csv" )]
        CSV = 0
    }
    

    静态添加的示例用法:

    var myDescription = myEnum.Description();
    
        12
  •  2
  •   wonea Ilya Smagin    8 年前

    利用一些较新的C语言功能,您可以减少行数:

    public static TAttribute GetEnumAttribute<TAttribute>(this Enum enumVal) where TAttribute : Attribute
    {
        var memberInfo = enumVal.GetType().GetMember(enumVal.ToString());
        return memberInfo[0].GetCustomAttributes(typeof(TAttribute), false).OfType<TAttribute>().FirstOrDefault();
    }
    
    public static string GetEnumDescription(this Enum enumValue) => enumValue.GetEnumAttribute<DescriptionAttribute>()?.Description ?? enumValue.ToString();
    
        13
  •  1
  •   saille    11 年前

    此扩展方法将使用其xmlenumattribute获取枚举值的字符串表示形式。如果不存在xmlenumattribute,则返回到enum.toString()。

    public static string ToStringUsingXmlEnumAttribute<T>(this T enumValue)
        where T: struct, IConvertible
    {
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("T must be an enumerated type");
        }
    
        string name;
    
        var type = typeof(T);
    
        var memInfo = type.GetMember(enumValue.ToString());
    
        if (memInfo.Length == 1)
        {
            var attributes = memInfo[0].GetCustomAttributes(typeof(System.Xml.Serialization.XmlEnumAttribute), false);
    
            if (attributes.Length == 1)
            {
                name = ((System.Xml.Serialization.XmlEnumAttribute)attributes[0]).Name;
            }
            else
            {
                name = enumValue.ToString();
            }
        }
        else
        {
            name = enumValue.ToString();
        }
    
        return name;
    }
    
        14
  •  1
  •   MeTitus    9 年前

    如果你想要完整的名单,你可以这样做

    typeof (PharmacyConfigurationKeys).GetFields()
            .Where(x => x.GetCustomAttributes(false).Any(y => typeof(DescriptionAttribute) == y.GetType()))
            .Select(x => ((DescriptionAttribute)x.GetCustomAttributes(false)[0]).Description);
    
        15
  •  1
  •   wonea Ilya Smagin    8 年前

    我这个答案是从一个枚举属性中设置一个组合框,这很好。

    然后我需要对相反的代码进行编码,以便从框中获得所选内容并返回正确类型的枚举。

    我还修改了代码来处理属性丢失的情况。

    为了下一个人的利益,这是我的最终解决方案

    public static class Program
    {
       static void Main(string[] args)
        {
           // display the description attribute from the enum
           foreach (Colour type in (Colour[])Enum.GetValues(typeof(Colour)))
           {
                Console.WriteLine(EnumExtensions.ToName(type));
           }
    
           // Get the array from the description
           string xStr = "Yellow";
           Colour thisColour = EnumExtensions.FromName<Colour>(xStr);
    
           Console.ReadLine();
        }
    
       public enum Colour
       {
           [Description("Colour Red")]
           Red = 0,
    
           [Description("Colour Green")]
           Green = 1,
    
           [Description("Colour Blue")]
           Blue = 2,
    
           Yellow = 3
       }
    }
    
    public static class EnumExtensions
    {
    
        // This extension method is broken out so you can use a similar pattern with 
        // other MetaData elements in the future. This is your base method for each.
        public static T GetAttribute<T>(this Enum value) where T : Attribute
        {
            var type = value.GetType();
            var memberInfo = type.GetMember(value.ToString());
            var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
    
            // check if no attributes have been specified.
            if (((Array)attributes).Length > 0)
            {
                return (T)attributes[0];
            }
            else
            {
                return null;
            }
        }
    
        // This method creates a specific call to the above method, requesting the
        // Description MetaData attribute.
        public static string ToName(this Enum value)
        {
            var attribute = value.GetAttribute<DescriptionAttribute>();
            return attribute == null ? value.ToString() : attribute.Description;
        }
    
        /// <summary>
        /// Find the enum from the description attribute.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="desc"></param>
        /// <returns></returns>
        public static T FromName<T>(this string desc) where T : struct
        {
            string attr;
            Boolean found = false;
            T result = (T)Enum.GetValues(typeof(T)).GetValue(0);
    
            foreach (object enumVal in Enum.GetValues(typeof(T)))
            {
                attr = ((Enum)enumVal).ToName();
    
                if (attr == desc)
                {
                    result = (T)enumVal;
                    found = true;
                    break;
                }
            }
    
            if (!found)
            {
                throw new Exception();
            }
    
            return result;
        }
    }
    

    }

        16
  •  0
  •   Ranco g0rski    11 年前

    伙计们,如果有帮助的话,我会和你们分享我的解决方案: 自定义属性定义:

        [AttributeUsage(AttributeTargets.Field,AllowMultiple = false)]
    public class EnumDisplayName : Attribute
    {
        public string Name { get; private set; }
        public EnumDisplayName(string name)
        {
            Name = name;
        }
    }
    

    现在,因为我在htmlhelper扩展的htmlhelper定义中需要它:

    public static class EnumHelper
    {
        public static string EnumDisplayName(this HtmlHelper helper,EPriceType priceType)
        {
            //Get every fields from enum
            var fields = priceType.GetType().GetFields();
            //Foreach field skipping 1`st fieldw which keeps currently sellected value
            for (int i = 0; i < fields.Length;i++ )
            {
                //find field with same int value
                if ((int)fields[i].GetValue(priceType) == (int)priceType)
                {
                    //get attributes of found field
                    var attributes = fields[i].GetCustomAttributes(false);
                    if (attributes.Length > 0)
                    {
                        //return name of found attribute
                        var retAttr = (EnumDisplayName)attributes[0];
                        return retAttr.Name;
                    }
                }
            }
            //throw Error if not found
            throw new Exception("Błąd podczas ustalania atrybutów dla typu ceny allegro");
        }
    }
    

    希望有帮助

        17
  •  0
  •   Mohit Dhawan    7 年前
        public enum DataFilters
        {
            [Display(Name= "Equals")]
            Equals = 1,// Display Name and Enum Name are same 
            [Display(Name= "Does Not Equal")]
            DoesNotEqual = 2, // Display Name and Enum Name are different             
        }
    

    在这种情况下,它将产生错误1“等于”

    public static string GetDisplayName(this Enum enumValue)
        {
            var enumMember = enumValue.GetType().GetMember(enumValue.ToString()).First();
            return enumMember.GetCustomAttribute<DisplayAttribute>() != null ? enumMember.GetCustomAttribute<DisplayAttribute>().Name : enumMember.Name;
        }
    

    因此,如果它是相同的,则返回枚举名称而不是显示名称,因为 EnumMember.getCustomAttribute()。 如果DisplayName和枚举名称相同,则获取空…..

        18
  •  -1
  •   Ian P    15 年前

    或者,您可以执行以下操作:

    Dictionary<FunkyAttributesEnum, string> description = new Dictionary<FunkyAttributesEnum, string>()
        {
          { FunkyAttributesEnum.NameWithoutSpaces1, "Name With Spaces1" },
          { FunkyAttributesEnum.NameWithoutSpaces2, "Name With Spaces2" },
        };
    

    并获得以下描述:

    string s = description[FunkyAttributesEnum.NameWithoutSpaces1];
    

    在我看来,这是一种更有效的方式来做你想做的事情,因为不需要反思。

        19
  •  -4
  •   nawfal Donny V.    12 年前

    还可以定义枚举值,如 Name_Without_Spaces ,如果需要说明,请使用 Name_Without_Spaces.ToString().Replace('_', ' ') 用空格替换下划线。