代码之家  ›  专栏  ›  技术社区  ›  RubenHerman

从枚举属性获取枚举

  •  32
  • RubenHerman  · 技术社区  · 14 年前

    我有

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

    public class StringValueAttribute : Attribute
    {
        private string _value;
    
        public StringValueAttribute(string value)
        {
            _value = value;
        }
    
        public string Value
        {
            get { return _value; }
        }
    }
    

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

    这可能吗?如果可能,怎么可能(这个 StringValue 匹配从组合框中选择的值)。

    6 回复  |  直到 11 年前
        1
  •  22
  •   ysrb    11 年前

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

    要调用它,只需执行以下操作:

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

    但这可能不是最好的解决方案,因为它与 Als 你可能想让这段代码可以重用。您可能想从我的解决方案中去掉代码,返回属性值,然后使用 Enum.Parse 就像你在问问题时所做的那样。

        2
  •  11
  •   Oliver    14 年前

    我用的是 DescriptionAttribute 从Microsoft和以下扩展方法:

    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;
    }
    
        3
  •  6
  •   Community CDub    7 年前

    这里有几个扩展方法,我使用这个确切的目的,我重写了这些使用您的 StringValueAttribute ,但就像 Oliver 我使用 DescriptionAttribute 在我的密码里。

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

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

    要调用它,只需执行以下操作:

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

    相反地

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

    并称之为:

    string description = Als.NietBeantwoord.StringValue()
    
        4
  •  2
  •   DLeh    6 年前

    从复制的 this highly upvoted question and answer Enum struct 这样你就可以使它为空 TEnum? 否则你会出错。

    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;
    }
    
        5
  •  1
  •   theraneman    14 年前

    Als temp = (Als)combo1.SelectedItem;
    int t = (int)temp;
    
        6
  •  0
  •   TylerBrinkley    6 年前

    Enums.NET 开源库。

    对于自定义属性,如 StringValueAttribute

    注册并存储自定义 EnumFormat StringValueAttribute.Value .

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

    然后使用自定义 枚举格式 .

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

    DescriptionAttribute

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

    如果您感兴趣,这就是如何获取与枚举值关联的字符串值的方法。

    string value = Als.NietBeantwoord.AsString(Format); // value == "Niet beantwoord"
    
        7
  •  0
  •   Joseph K    5 年前

    我做了一个更 泛型 解决方案。
    任何 属性,甚至使用字符串以外的其他类型。

    using System;
    
    namespace EnumTest
    {
        public static class EnumExtensions
        {
            #region Get enum from Attribute
            /// <summary>
            /// Searches the enum element which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
            /// Throws exception, if there is no enum element found which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
            /// </summary>
            /// <param name="attributeType">the type of the attribute. e.g. typeof(System.ComponentModel.DescriptionAttribute)</param>
            /// <param name="attributePropertyName">the property of the attribute to search. At DescriptionAttribute, this is "Description"</param>
            /// <param name="searchValue">the value to search</param>
            public static TEnum FromAttributeValueToEnum<TEnum>(Type attributeType, string attributePropertyName, object searchValue)
            where TEnum : struct, Enum
            {
                TEnum? result = FromAttributeValueToNullableEnum<TEnum>(attributeType, attributePropertyName, searchValue);
    
                if (result.HasValue)
                {
                    return result.Value;
                }
    
                Type enumType = typeof(TEnum);
                throw new ArgumentException($"The enum type {enumType.FullName} has no element with a {attributeType.FullName} with {attributePropertyName} property equivalent to '{searchValue}'");
            }
    
            /// <summary>
            /// Searches the enum element which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
            /// Returns fallBackValue, if there is no enum element found which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
            /// </summary>
            /// <param name="attributeType">the type of the attribute. e.g. typeof(System.ComponentModel.DescriptionAttribute)</param>
            /// <param name="attributePropertyName">the property of the attribute to search. At DescriptionAttribute, this is "Description"</param>
            /// <param name="searchValue">the value to search</param> 
            public static TEnum FromAttributeValueToEnum<TEnum>(Type attributeType, string attributePropertyName, object searchValue, TEnum fallBackValue)
            where TEnum : struct, Enum
            {
                TEnum? result = FromAttributeValueToNullableEnum<TEnum>(attributeType, attributePropertyName, searchValue);
    
                if (result.HasValue)
                {
                    return result.Value;
                }
    
                return fallBackValue;
            }
    
            /// <summary>
            /// Searches the enum element which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
            /// Returns null, if there is no enum element found which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
            /// </summary>
            /// <param name="attributeType">the type of the attribute. e.g. typeof(System.ComponentModel.DescriptionAttribute)</param>
            /// <param name="attributePropertyName">the property of the attribute to search. At DescriptionAttribute, this is "Description"</param>
            /// <param name="searchValue">the value to search</param> 
            public static TEnum? FromAttributeValueToNullableEnum<TEnum>(Type attributeType, string attributePropertyName, object searchValue)
            where TEnum : struct, Enum
            {
                Type enumType = typeof(TEnum);
                if (!enumType.IsEnum)
                {
                    throw new ArgumentException($"The type {enumType.FullName} is no Enum!");
                }
    
                if (attributeType == null)
                {
                    throw new ArgumentNullException(nameof(attributeType));
                }
    
                if (!typeof(Attribute).IsAssignableFrom(attributeType))
                {
                    throw new ArgumentException($"The type {attributeType.FullName} is no Attribute!", nameof(attributeType));
                }
    
                var propertyInfoAttributePropertyName = attributeType.GetProperty(attributePropertyName);
    
                if (propertyInfoAttributePropertyName == null)
                {
                    throw new ArgumentException($"The type {attributeType.FullName} has no (public) property with name {attributePropertyName}", nameof(attributeType));
                }
    
                foreach (var field in enumType.GetFields())
                {
                    var attribute = Attribute.GetCustomAttribute(field, attributeType);
                    if (attribute == null)
                    {
                        continue;
                    }
    
                    object attributePropertyValue = propertyInfoAttributePropertyName.GetValue(attribute);
    
                    if (attributePropertyValue == null)
                    {
                        continue;
                    }
    
                    if (attributePropertyValue.Equals(searchValue))
                    {
                        return (TEnum)field.GetValue(null);
                    }
                }
    
                return null;
            }
            #endregion
        }
    }
    

    Als Beantwoord = EnumExtensions.FromAttributeValueToEnum<Als>(typeof(StringValueAttribute), nameof(StringValueAttribute.Value), "Beantwoord");
    

    高级示例:

    public class IntValueAttribute : Attribute
    {
        public IntValueAttribute(int value)
        {
            Value = value;
        }
    
        public int Value { get; private set; }
    }
    
    public enum EnumSample
    {
        [Description("Eins")]
        [IntValue(1)]
        One,
    
        [Description("Zwei")]
        [IntValue(2)]
        Two,
    
        [Description("Drei")]
        [IntValue(3)]
        Three
    }
    
    EnumSample one = EnumExtensions.FromAttributeValueToEnum<EnumSample>(typeof(DescriptionAttribute), nameof(DescriptionAttribute.Description), "Eins");
    EnumSample two = EnumExtensions.FromAttributeValueToEnum<EnumSample>(typeof(IntValueAttribute), nameof(IntValueAttribute.Value), 2);