2012-03-02 2 views
1

SLIGHT UPDATE НИЖЕПопытка использовать [Описание] атрибут аннотаций данных с существующим кодом

Я пытаюсь использовать [Description] данных атрибутов аннотаций с enums, чтобы отобразить понятное имя. Я много искал и не мог ничего реализовать. Прямо сейчас у меня есть код, который будет отображать enum в виде строки (с использованием расширения), но мне не нравится ThisIsAnEnum как имя enum (которое разнесено расширением строки), и это запрещает мне иметь более длинные имена (что я необходимо поддерживать), например, для элемента переключателя. Моя цель состоит в том, чтобы иметь более длинные описания для элементов переключателя без необходимости писать действительно длинные перечисления. Расширение/помощник, вероятно, будет правильным путем, но мне нужно «подгонять» его в код, который я использую, а именно, где я не смог использовать множество примеров.

Код, который я использую, является общим, в зависимости от какой-либо логики отображается список переключателей, список флажков, выпадающий список, список выбора или обычные текстовые поля. Для списков нескольких элементов используются enum, а имя enum - это то, что отображается (после использования расширения строки).

Вот конкретный код, который отображает перечисление:

public static IEnumerable<SelectListItem> GetItemsFromEnum<T> 
    (T selectedValue = default(T)) where T : struct 
    { 
     return from name in Enum.GetNames(typeof(T)) 
       let enumValue = Convert.ToString((T)Enum.Parse(typeof(T), name, true)) 

       select new SelectListItem 
       { 
        Text = name.ProperCase(), 
        Value = enumValue, 
        Selected = enumValue.Equals(selectedValue) 
       }; 
    } 

ProperCase класс, который изменяет enum к чему-то читаемым.

я нашел то, что почти работали:

public static string GetEnumDescription<TEnum>(TEnum value) 
    { 
     FieldInfo fi = value.GetType().GetField(value.ToString()); 

     DescriptionAttribute[] attributes = 
      (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); 

     if ((attributes != null) && (attributes.Length > 0)) 
      return attributes[0].Description; 
     else 
      return value.ToString(); 
    } 

в этом случае я изменил код из Text = name.ProperCase(), в Text = name.GetEnumDescription(...), но если я ставлю value в скобках я получаю сообщение «не существует в текущем контексте» (который я пытался исправить, но только что сделал проблему хуже). Если я оставлю его пустым, я получаю «Нет перегрузки для ... принимает 0 аргументов» (опять же, понятно - но я не знаю, как исправить). И если я ставлю name в скобках код компилируется, но при просмотре страницы я получаю «Ссылка на объект не установлен ...» ошибка в этой строке:

DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes 
    (typeof(DescriptionAttribute), false); 

Я потратил много времени на это и знаю, что мой камнем преткновения является

Text = name.ProperCase(), 

код. Любые идеи/помощь? Заранее спасибо.

UPDATE:

Если я:

Text = GetEnumDescription(selectedValue), 

Я на самом деле получить [Description] текст, однако, он просто показывает первое перечисление. Итак, если у меня есть 5 перечислений с разными [Description], код просто повторяет [Description] для первого перечисления 5 раз вместо отображения по-разному для каждого. Надеюсь, это имеет смысл и сужает проблему.

+0

Возможный дубликат [Get the Enum value Описание] (http://stackoverflow.com/questions/297299/get-the-enumt-value-description) – jrummell

+0

Не видя, как это возможно, повторяющийся вопрос. Я считаю, что ответы на другую проблему (или, по крайней мере, я не могу найти там какое-либо решение для работы), но я откладываю ваш опыт. – REMESQ

+0

Связанный вопрос содержит часть 'GetEnumDescription()'. Раньше я не видел часть DropDownList. – jrummell

ответ

2

Я бы рекомендовал вам Display атрибут:

public static IEnumerable<SelectListItem> GetItemsFromEnum<T>(T selectedValue = default(T)) where T : struct 
{ 
    return 
     from name in Enum.GetNames(typeof(T)) 
     let enumValue = Convert.ToString((T)Enum.Parse(typeof(T), name, true)) 
     select new SelectListItem 
     { 
      Text = GetEnumDescription(name, typeof(T)), 
      Value = enumValue, 
      Selected = name == selectedValue.ToString() 
     }; 
} 

public static string GetEnumDescription(string value, Type enumType) 
{ 
    var fi = enumType.GetField(value.ToString()); 
    var display = fi 
     .GetCustomAttributes(typeof(DisplayAttribute), false) 
     .OfType<DisplayAttribute>() 
     .FirstOrDefault(); 
    if (display != null) 
    { 
     return display.Name; 
    } 
    return value; 
} 

и тогда вы могли бы:

public enum Foo 
{ 
    [Display(Name = "value 1")] 
    Value1, 

    Value2, 

    [Display(Name = "value 3")] 
    Value3 
} 

И теперь вы могли бы:

var foo = Foo.Value2; 
var values = GetItemsFromEnum(foo); 

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

Это, как говорится, лично я бы рекомендовал вам держаться подальше от перечислений на моделях просмотра, так как они не играют хорошо с тем, что встроено в ASP.NET MVC, и вам придется переосмыслить большинство вещей.

+0

Спасибо за это Дарин. Он работает, чтобы отображать атрибут для каждого элемента, однако строка '.FirstOrDefault()' вызывает падение в обход текста «Выбрать один», а в случае флажков он автоматически проверяет первый элемент (который в моем сценарий не является предпочтительным). Есть ли способ обойти это? Благодарю. – REMESQ

+0

@REMESQ, попробуйте нулевое перечисление, если вы хотите использовать значение по умолчанию для поля выбора. –

+0

Извините за мое невежество: я уже делаю, например 'public Foo? FooDropDown {get; задавать; } 'и единственный способ, которым я знаю, как обнулить перечисление, - это сделать public Foo? FooDropDown = null; 'которые, очевидно, не будут работать вместе. Могу ли я беспокоить вас примером для кода, который вы опубликовали? Благодарю. – REMESQ

Смежные вопросы