Получить описание значения Enum <T>

У меня есть класс enumHelper, который содержит:

public static IList<T> GetValues()
{
  IList<T> list = new List<T>();
  foreach (object value in Enum.GetValues(typeof(T)))
  {
    list.Add((T)value);
  }
  return list;
}

и

public static string Description(Enum value)
{
  Attribute DescAttribute = LMIGHelper.GetAttribute(value, typeof(DescriptionAttribute));
  if (DescAttribute == null)
    return value.ToString();
  else
    return ((DescriptionAttribute)DescAttribute).Description;
}

мое перечисление выглядит примерно так:

public enum OutputType
{
    File,
    [Description("Data Table")]
    DataTable
}

Все идет нормально. Все предыдущие работают нормально. Теперь я хочу добавить новый помощник для возврата BindingList>, чтобы я мог связать любое перечисление с любым комбо, используя

BindingList<KeyValuePair<OutputType, string>> list = Enum<OutputType>.GetBindableList();
cbo.datasource=list;
cbo.DisplayMember = "Value";
cbo.ValueMember = "Key";

Для этого я добавил:

public static BindingList<KeyValuePair<T, string>> GetBindingList()
{
    BindingList<KeyValuePair<T, string>> list = new BindingList<KeyValuePair<T, string>>();
    foreach (T value in Enum<T>.GetValues())
    {
        string Desc = Enum<T>.Description(value);
        list.Add(new KeyValuePair<T, string>(value, Desc));
    }
    return list;
}

Но Enum.Description (value) даже не компилируется: Аргумент '1': невозможно преобразовать из 'T' в 'System.Enum'

Как я могу это сделать? Это вообще возможно?

Спасибо.

Ваш метод описания должен быть методом расширения? Если да, то вы пропустили это ключевое слово.

Jeff Yates 19.11.2008 01:26

См. Мой ответ на этот вопрос stackoverflow.com/questions/6145888/…

Nick 20.04.2016 20:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
2
10 100
3

Ответы 3

Enum не имеет метода Description (). Лучшее, что вы могли бы сделать, - это реализовать в вашем перечислении интерфейс с методом Description (). Если вы сделаете это, то сможете

public static BindingList<KeyValuePair<T extends _interface_, String>> getBindingList()

а затем внутри этого вы можете ссылаться на

T foo = ...?
foo.Description(...);

Вам следует изменить:

public static string Description(Enum value)
{
  ...
}

к

public static string Description(T value)
{
   ...
}

поэтому он принимает значение перечисления. Теперь вот где возникает сложность: у вас есть значение, но атрибуты украшают поле, которое содержит значение.

На самом деле вам нужно поразмыслить над полями перечисления и сравнить значение каждого с заданным вами значением (результаты должны быть кэшированы для повышения производительности):

foreach(var field in typeof(T).GetFields())
{
    T fieldValue;

    try
    {
        fieldValue = (T) field.GetRawConstantValue();
    }
    catch(InvalidOperationException)
    {
        // For some reason, one of the fields returned is {Int32 value__},
        // which throws an InvalidOperationException if you try and retrieve
        // its constant value.
        //
        // I am unsure how to check for this state before
        // attempting GetRawConstantValue().

        continue;
    }

    if (fieldValue == value)
    {
        var attribute = LMIGHelper.GetAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;

        return attribute == null ? value.ToString() : attribute.Description;
    }
}

Изменить ответ на следующий вопрос

В методе FillComboFromEnum отсутствует параметр типа для перечисления. Попробуй это:

public static void FillComboFromEnum<T>(ComboBox Cbo, BindingList<KeyValuePair<T, string>> List) where T : struct

Обратите внимание, что я ограничил тип структурой. Это не ограничение полного перечисления, но оно ближе, чем ничего.

Взгляните на этот статья. Вы можете сделать это, используя атрибут System.ComponentModel.DescriptionAttribute или создав свой собственный атрибут:

/// <summary>
/// Provides a description for an enumerated type.
/// </summary>
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field, 
 AllowMultiple = false)]
public sealed class EnumDescriptionAttribute :  Attribute
{
   private string description;

   /// <summary>
   /// Gets the description stored in this attribute.
   /// </summary>
   /// <value>The description stored in the attribute.</value>
   public string Description
   {
      get
      {
         return this.description;
      }
   }

   /// <summary>
   /// Initializes a new instance of the
   /// <see cref = "EnumDescriptionAttribute"/> class.
   /// </summary>
   /// <param name = "description">The description to store in this attribute.
   /// </param>
   public EnumDescriptionAttribute(string description)
       : base()
   {
       this.description = description;
   }
} 

Затем вам нужно украсить значения перечисления этим новым атрибутом:

public enum SimpleEnum
{
   [EnumDescription("Today")]
   Today,

   [EnumDescription("Last 7 days")]
   Last7,

   [EnumDescription("Last 14 days")]
   Last14,

   [EnumDescription("Last 30 days")]
   Last30,

   [EnumDescription("All")]
   All
} 

Вся «магия» происходит в следующих методах расширения:

/// <summary>
/// Provides a static utility object of methods and properties to interact
/// with enumerated types.
/// </summary>
public static class EnumHelper
{
   /// <summary>
   /// Gets the <see cref = "DescriptionAttribute" /> of an <see cref = "Enum" /> 
   /// type value.
   /// </summary>
   /// <param name = "value">The <see cref = "Enum" /> type value.</param>
   /// <returns>A string containing the text of the
   /// <see cref = "DescriptionAttribute"/>.</returns>
   public static string GetDescription(this Enum value)
   {
      if (value == null)
      {
         throw new ArgumentNullException("value");
      }

      string description = value.ToString();
      FieldInfo fieldInfo = value.GetType().GetField(description);
      EnumDescriptionAttribute[] attributes =
         (EnumDescriptionAttribute[])
       fieldInfo.GetCustomAttributes(typeof(EnumDescriptionAttribute), false);

      if (attributes != null && attributes.Length > 0)
      {
         description = attributes[0].Description;
      }
      return description;
   }

   /// <summary>
   /// Converts the <see cref = "Enum" /> type to an <see cref = "IList" /> 
   /// compatible object.
   /// </summary>
   /// <param name = "type">The <see cref = "Enum"/> type.</param>
   /// <returns>An <see cref = "IList"/> containing the enumerated
   /// type value and description.</returns>
   public static IList ToList(this Type type)
   {
      if (type == null)
      {
         throw new ArgumentNullException("type");
      }

      ArrayList list = new ArrayList();
      Array enumValues = Enum.GetValues(type);

      foreach (Enum value in enumValues)
      {
         list.Add(new KeyValuePair<Enum, string>(value, GetDescription(value)));
      }

      return list;
   }
} 

Наконец, вы можете просто привязать поле со списком:

combo.DataSource = typeof(SimpleEnum).ToList();

Оооо, вы могли бы написать это в своем ответе.

Henrik 01.03.2011 16:32

Есть ли какая-то конкретная причина использовать здесь ArrayList? Разве List <T> не был бы лучше?

nawfal 10.06.2013 11:45

@Scott Спасибо за ваш код. Если мы хотим вернуть значение int вместо перечисления в списке. мы можем использовать Convert.toInt (значение). ref: stackoverflow.com/questions/908543/… надеюсь, что это кому-то поможет.

Ram 02.02.2014 11:36

Другие вопросы по теме