2017-02-20 9 views
2

Я пытаюсь получить свойства DisplayAttribute, работающие для enum, поэтому я могу указать доступные значения (чтобы открыть API RESTful).Enum Reflection с .NET Core

У меня есть перечисление следующим образом:

/// <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 
} 

Затем я сделал некоторые вспомогательные методы, как так:

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

Использование для этого было бы:

var types = Reflection.GetEnumPossibilities<ProposalTypes>(); 

То, что кажется однако, это происходит в методе GetAttribute<TAttribute>, когда я пытаюсь получить атрибут, который я ищу w с:

var attributes = typeInfo.GetCustomAttributes<TAttribute>(); 

... полученное значение представляет собой пустое перечисление, возвращая обратно нулевое значение. Из всего, что я читал, это должно работать нормально, и я должен вернуть связанный DisplayAttribute ... но я возвращаю нулевое значение.

Что я делаю неправильно?

+0

Из любопытства, что вы делаете с этим Словарем (возвращаемое значение 'GetEnumPossibilities') в конце? Если вы возвращаете это где-то как JSON, вы испытываете массу неприятностей без необходимости. JSON.NET будет правильно сериализовать ваши атрибуты. –

+0

@HristoYankov Я использую это, чтобы создать конечную точку, которая определяет возможные типы, чтобы информировать интерфейс пользователя API. –

ответ

4

Проблема заключается в том, что вы ищете атрибуты типа ProposalTypes, а не значения типа. See this Question для получения информации об атрибутах значений перечисления.

Точнее, в 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; 
} 
+1

Хм. Наверное, я рассматривал значение перечисления как свой собственный тип, и это не то, на что C# смотрит на него как. Спасибо за помощь, это было очень неприятно. –

+0

Да, я вижу, как у вас возникнут проблемы с такими предположениями. Мой подсказку отладки заключалась бы в том, что если бы вы посмотрели на то, что вернуло GetType, вы, надеюсь, были бы указаны в правильном направлении, понимая, что значения не сами по себе. Я должен был искать, как получить атрибут от значений, хотя. ;-) – Chris