尝试将[Description]数据注释属性与现有代码一起使用

时间:2012-03-02 13:54:42

标签: asp.net-mvc-3

以下稍后更新

我正在尝试将[Description]数据注释属性与enums一起使用,以显示友好名称。我经常搜索很多东西,无法实现任何目标。现在我的代码将enum显示为字符串(使用扩展名),但我不喜欢ThisIsAnEnum作为enum名称(由字符串扩展名分隔)并禁止我使用更长的名称(我需要维护),例如单选按钮项目。我的目标是对单选按钮项进行更长的描述,而不必编写真正长的枚举。扩展/帮助可能是正确的方法,但我需要"适合"它进入我正在使用的代码中,这是我在那里使用许多示例失败的地方。

我使用的代码是通用的,因为根据某些逻辑,显示单选按钮列表,复选框列表,下拉列表,选择列表或常规文本框。对于多项目列表,使用enumenum名称显示(使用字符串扩展名后)。

以下是显示枚举的特定代码:

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放在括号中,我会得到一个&#34;在当前上下文中不存在&#34;消息(我尝试修复但只是让问题变得更糟)。如果我把它留空,我会得到&#34;没有超载......需要0个参数&#34; (再次,可以理解 - 但我不知道如何解决)。如果我将name放在括号中,代码会编译,但在查看页面时,我会得到&#34;对象引用未设置...&#34;这一行出错:

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

我花了很多时间在这上面,知道我的绊脚石是

Text = name.ProperCase(),

代码。任何想法/帮助?提前谢谢。

更新

如果我这样做:

Text = GetEnumDescription(selectedValue),

我实际上得到[Description]文本,但是,它只显示第一个枚举。因此,如果我有5个枚举,但所有[Description]代码都不同,则代码只会为第一个枚举重复[Description] 5次而不是为每个枚举显示不同的内容。我希望这有意义并缩小问题范围。

1 个答案:

答案 0 :(得分: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);

另请注意,我修改了LINQ表达式中的Selected子句,因为它不正确。

话虽如此,我个人建议你远离视图模型上的枚举,因为它们不能很好地与内置的ASP.NET MVC一起使用,你将不得不重新发明大部分内容。