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

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?如果属性属于枚举本身,我可以想到如何做到这一点,但我不知道如何从枚举的值中获得它。


当前回答

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

其他回答

这是一个使用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);

NuGet包枚举。Net对此提供了很好的支持:

var value = FunkyAttributesEnum.NameWithoutSpaces1;
string description = value.AsString(EnumFormat.Description); // => "Name With Spaces1"

该软件包简单、直观、完整。 它是类型安全的,并具有缓存以避免重复反射。

GitHub存储库有更多信息,包括本机Enum的限制和功能演示:

获取属性; 国旗操作; Enum格式(用于ToString或从string解析Enum); 使用enumbers . getmembers <MyEnum>()丰富迭代所有值; 等。

这段代码应该为任何枚举提供了一个不错的扩展方法,使您可以检索泛型属性。我相信它与上面的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><![CDATA[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;
    }
}

用法如下:

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

除了AdamCrawford响应之外,我还进一步创建了一个更专门的扩展方法来获取它的描述。

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

因此,要获得描述,您可以使用原始扩展方法as

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

或者你可以简单地调用这里的扩展方法:

string desc = myEnumVariable.GetAttributeDescription();

这应该会使您的代码更具可读性。

模型

我们用这个模型来充实我们的价值观

public class MemberTypeModel : IDto
{
    public string MemberAttributeName { get; set; }
    public string MemberName { get; set; }
    public int MemberValue { get; set; }
}

Enum

我们的目标是枚举

public enum MemberType
{
    [FieldText("Yönetim Kurul Üyesi")]
    BoardManager = 0,

    [FieldText("Temsilci")]
    Representative = 1,

    [FieldText("Üye")]
    Member = 2
}

辅助方法

我们将使用helper方法来获取自定义属性对象

public T GetMemberCustomText<T>(MemberType memberType) where T : Attribute
{
    var enumType = memberType.GetType();
    var name = Enum.GetName(enumType, memberType);
    return enumType.GetField(name).GetCustomAttributes(false).OfType<T>().SingleOrDefault();
}

Get方法

首先,我们提取枚举值并将它们转换为枚举类型。然后,通过Linq选择查询我们知道;

MemberAttributeName字段与helper方法, 带有Enum的MemberName字段。GetName方法, 将MemberValue字段转换为int类型, 我们把它填好,然后变成一个清单。


public List<MemberTypeModel> GetMemberTypes()
{
    var memberTypes = Enum.GetValues(typeof(MemberType))
        .Cast<MemberType>()
        .Select(et => new MemberTypeModel
        {
            MemberAttributeName = GetMemberCustomText<FieldText>(et).Text,
            MemberName = Enum.GetName(et.GetType(), et),
            MemberValue = (int)et
        }).ToList();
    return memberTypes;
}