.NET Core的枚举反射

Jer*_*acs 2 c# reflection .net-core asp.net-core

我正在尝试使DisplayAttribute属性适用于enum,因此我可以列出可用的值(向RESTful API公开)。

我有一个枚举如下:

/// <summary>
/// Available Proposal Types
/// </summary>
public enum ProposalTypes
{
    Undefined = 0,

    /// <summary>
    /// Propose an administrative action.
    /// </summary>
    [Display(Name = "Administrative", Description = "Propose an administrative action.")]
    Administrative,

    /// <summary>
    /// Propose some other action.
    /// </summary>
    [Display(Name = "Miscellaneous", Description = "Propose some other action.")]
    Miscellaneous
}
Run Code Online (Sandbox Code Playgroud)

然后,我制作了一些辅助方法,如下所示:

    /// <summary>
    ///     A generic extension method that aids in reflecting
    ///     and retrieving any attribute that is applied to an `Enum`.
    /// </summary>
    public static TAttribute GetAttribute<TAttribute>(this Enum enumValue) where TAttribute : Attribute
    {
        var type = enumValue.GetType();
        var typeInfo = type.GetTypeInfo();
        var attributes = typeInfo.GetCustomAttributes<TAttribute>();
        var attribute = attributes.FirstOrDefault();
        return attribute;
    }

    /// <summary>
    /// Returns a list of possible values and their associated descriptions for a type of enumeration.
    /// </summary>
    /// <typeparam name="TEnum"></typeparam>
    /// <returns></returns>
    public static IDictionary<string, string> GetEnumPossibilities<TEnum>() where TEnum : struct
    {
        var type = typeof(TEnum);
        var info = type.GetTypeInfo();
        if (!info.IsEnum) throw new InvalidOperationException("Specified type is not an enumeration.");


        var results = new Dictionary<string, string>();
        foreach (var enumName in Enum.GetNames(type)
            .Where(x => !x.Equals("Undefined", StringComparison.CurrentCultureIgnoreCase))
            .OrderBy(x => x, StringComparer.CurrentCultureIgnoreCase))
        {
            var value = (Enum)Enum.Parse(type, enumName);
            var displayAttribute = value.GetAttribute<DisplayAttribute>();
            results[enumName] = $"{displayAttribute?.Name ?? enumName}: {displayAttribute?.Description ?? enumName}";
        }
        return results;
    }
Run Code Online (Sandbox Code Playgroud)

用法是:

var types = Reflection.GetEnumPossibilities<ProposalTypes>();
Run Code Online (Sandbox Code Playgroud)

但是,GetAttribute<TAttribute>当我尝试获取要查找的属性时,似乎正在发生这种情况:

var attributes = typeInfo.GetCustomAttributes<TAttribute>();
Run Code Online (Sandbox Code Playgroud)

...结果值是一个空的枚举,因此返回空值。从我读过的所有内容来看,这应该可以正常工作,并且我应该找回关联的值DisplayAttribute……但是我找回一个空值。

我究竟做错了什么?

Chr*_*ris 5

问题是您正在寻找ProposalTypes类型的属性,而不是类型的值。有关 获取枚举值的属性的信息,请参见此问题

更确切地说,GetAttribute您需要获取代表您的特定值的成员并对其进行调用GetCustomAttributes。您的方法将如下所示:

public static TAttribute GetAttribute<TAttribute>(this Enum enumValue) where TAttribute : Attribute
{
    var type = enumValue.GetType();
    var typeInfo = type.GetTypeInfo();
    var memberInfo = typeInfo.GetMember(enumValue.ToString());
    var attributes = memberInfo[0].GetCustomAttributes<TAttribute>();
    var attribute = attributes.FirstOrDefault();
    return attribute;
}
Run Code Online (Sandbox Code Playgroud)