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

using System.ComponentModel; // for DescriptionAttribute

enum FunkyAttributesEnum
{
    [Description("Name With Spaces1")]
    NameWithoutSpaces1,    
    [Description("Name With Spaces2")]
    NameWithoutSpaces2
}

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

价值很简单:

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

但我如何获得描述属性的值,以填充Tuple.Desc?如果属性属于枚举本身,我可以想到如何做到这一点,但我不知道如何从枚举的值中获得它。


当前回答

这就是我在不使用。net core 3.1的自定义helper或扩展的情况下解决它的方法。

public enum YourEnum
{
    [Display(Name = "Suryoye means Arameans")]
    SURYOYE = 0,
    [Display(Name = "Oromoye means Syriacs")]
    OROMOYE = 1,
}

剃须刀

@using Enumerations

foreach (var name in Html.GetEnumSelectList(typeof(YourEnum)))
{
    <h1>@name.Text</h1>
}

其他回答

利用一些较新的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();

我已经创建了一个扩展方法,它将返回c#中枚举中所有元素的描述。

public static List<string> GetAllEnumDescriptions(this Type enumType)
    {
        try
        {
            var enumList = Enum.GetValues(enumType).Cast<Enum>().ToList();
            List<string> result = new List<string>();
            foreach (var enumItem in enumList)
            {
                result.Add(enumItem.EnumDescription());
            }
            return result;
        }
        catch (Exception ex)
        {
            return new List<string>();
        }
    }

此方法将使用内置的EnumDescription()扩展方法添加枚举中元素的描述。

对于一些程序员的幽默,一行代码就像一个笑话:

public static string GetDescription(this Enum value) => value.GetType().GetMember(value.ToString()).First().GetCustomAttribute<DescriptionAttribute>() is DescriptionAttribute attribute ? attribute.Description : string.Empty;

以更易读的形式:

using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

public static class EnumExtensions
{
    // get description from enum:

    public static string GetDescription(this Enum value)
    {
        return value.GetType().
            GetMember(value.ToString()).
            First().
            GetCustomAttribute<DescriptionAttribute>() is DescriptionAttribute attribute
            ? attribute.Description
            : throw new Exception($"Enum member '{value.GetType()}.{value}' doesn't have a [DescriptionAttribute]!");
    }

    // get enum from description:

    public static T GetEnum<T>(this string description) where T : Enum
    {
        foreach (FieldInfo fieldInfo in typeof(T).GetFields())
        {
            if (fieldInfo.GetCustomAttribute<DescriptionAttribute>() is DescriptionAttribute attribute && attribute.Description == description)
                return (T)fieldInfo.GetRawConstantValue();
        }

        throw new Exception($"Enum '{typeof(T)}' doesn't have a member with a [DescriptionAttribute('{description}')]!");
    }
}

添加我的解决方案的Net Framework和NetCore。

我在我的Net Framework实现中使用了这个:

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

这个扩展方法将使用枚举值的XmlEnumAttribute获得枚举值的字符串表示形式。如果没有XmlEnumAttribute,则返回到枚举. 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;
}