Попытка использовать атрибут аннотации [Description] с существующим кодом - PullRequest
1 голос
/ 02 марта 2012

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(),

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

ОБНОВЛЕНИЕ:

Если я сделаю:

Text = GetEnumDescription(selectedValue),

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

1 Ответ

2 голосов
/ 02 марта 2012

Я бы порекомендовал вам атрибут 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, и вам придется заново изобретать большинство вещей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...