如何通过MVC剃刀代码获取Enum成员的显示名称属性?


211

我的模型中有一个名为“ Promotion”的属性,其类型是一个名为“ UserPromotion”的标志枚举。我的枚举成员的显示属性设置如下:

[Flags]
public enum UserPromotion
{
    None = 0x0,

    [Display(Name = "Send Job Offers By Mail")]
    SendJobOffersByMail = 0x1,

    [Display(Name = "Send Job Offers By Sms")]
    SendJobOffersBySms = 0x2,

    [Display(Name = "Send Other Stuff By Sms")]
    SendPromotionalBySms = 0x4,

    [Display(Name = "Send Other Stuff By Mail")]
    SendPromotionalByMail = 0x8
}

现在,我希望能够在视图中创建说出ul以显示“促销”属性的选定值。到目前为止,这是我所做的,但问题是如何在这里获取显示名称?

<ul>
    @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
    {
        var currentPromotion = (int)Model.JobSeeker.Promotion;
        if ((currentPromotion & aPromotion) == aPromotion)
        {
        <li>Here I don't know how to get the display attribute of "currentPromotion".</li>
        }
    }
</ul>

12
MVC5确实支持枚举的DisplayName属性。
Bart Calixto 2014年

10
要更清楚:只有System.ComponentModel.DataAnnotations.DisplayAttribute。不System.ComponentModel.DisplayNameAttribute
kamranicus

1
这是否包括使用反射并因此影响性能?因为这将被称为很多时间。
Nico

Answers:


182

更新

第一个解决方案着重于从枚举中获取显示名称。下面的代码应该是您的问题的确切解决方案。

您可以将此帮助程序类用于枚举:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumHelper<T>
{
    public static IList<T> GetValues(Enum value)
    {
        var enumValues = new List<T>();

        foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
        {
            enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
        }
        return enumValues;
    }

    public static T Parse(string value)
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }

    public static IList<string> GetNames(Enum value)
    {
        return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
    }

    public static IList<string> GetDisplayValues(Enum value)
    {
        return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
    }

    private static string lookupResource(Type resourceManagerProvider, string resourceKey)
    {
        foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
        {
            if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
            {
                System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
                return resourceManager.GetString(resourceKey);
            }
        }

        return resourceKey; // Fallback with the key name
    }

    public static string GetDisplayValue(T value)
    {
        var fieldInfo = value.GetType().GetField(value.ToString());

        var descriptionAttributes = fieldInfo.GetCustomAttributes(
            typeof(DisplayAttribute), false) as DisplayAttribute[];

        if (descriptionAttributes[0].ResourceType != null)
            return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);

        if (descriptionAttributes == null) return string.Empty;
        return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
    }
}

然后可以在视图中使用它,如下所示:

<ul>
    @foreach (var value in @EnumHelper<UserPromotion>.GetValues(UserPromotion.None))
    {
         if (value == Model.JobSeeker.Promotion)
        {
            var description = EnumHelper<UserPromotion>.GetDisplayValue(value);
            <li>@Html.DisplayFor(e => description )</li>
        }
    }
</ul>

希望能帮助到你!:)


8
所有答案都使用.ToString,但是从stackoverflow.com/q/483794/179311可以使用Enum.GetName来代替。
bradlis7 2014年

value.GetType()。GetField(value.ToString())正是我想要的!
cdie

通过添加一些空值检查可以很好地解决这个问题,但是如果您不使用dotfuscation,则stackoverflow.com/a/4412730/852806上的回答似乎更简单。
HockeyJ

5
GetDisplayValue您应该首先进行测试,descriptionAttributes == null然后再尝试访问数组:descriptionAttributes[0]。否则,您可能会引发异常,并且下面检查null的行将永远不会为真。
罗伯特S.17年

我建议进行较小的更改:公共静态IList <T> GetValues(枚举值)可以是公共静态IList <T> GetValues(T值)。EnumHelper <T>到=>公共静态类EnumHelper <T>,其中T:struct,IConvertible。也许是静态构造函数?静态EnumHelper(){如果(!typeof(T).IsEnum){抛出新的ArgumentException(“ T必须为枚举类型”);}
汤姆(Tom)

172

一线-流利的语法

public static class Extensions
{
    /// <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
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<TAttribute>();
    }
}

public enum Season 
{
   [Display(Name = "It's autumn")]
   Autumn,

   [Display(Name = "It's winter")]
   Winter,

   [Display(Name = "It's spring")]
   Spring,

   [Display(Name = "It's summer")]
   Summer
}

public class Foo 
{
    public Season Season = Season.Summer;

    public void DisplayName()
    {
        var seasonDisplayName = Season.GetAttribute<DisplayAttribute>();
        Console.WriteLine("Which season is it?");
        Console.WriteLine (seasonDisplayName.Name);
    } 
}

输出量

现在是哪个季节
夏天到了


2
不存在GetCustomAttribute的定义
Tito

3
@Tito确保您的项目为目标.NET Framework 4.5并且包含以下名称空间System.Net System.ComponentModel.DataAnnotations
Aydin

8
使用System.Reflection; 使用System.ComponentModel.DataAnnotations; 是我需要的。
Sinned Lolwut

1
多么糟糕的命名约定!
curiousBoy

@curiousBoy GetAttribute<TAttribute>糟糕的命名约定如何?它检索您指定的属性,并像所有公共方法一样使用pascal大小写。
艾登(Aydin)

137

建立在Aydin的一个很好的答案上,这是一个不需要任何类型参数的扩展方法。

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumExtensions
{
    public static string GetDisplayName(this Enum enumValue)
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<DisplayAttribute>()
                        .GetName();
    }
}

注意:应该使用GetName()代替Name属性。这样可以确保如果使用ResourceType属性,则将返回本地化的字符串。

要使用它,只需在视图中引用枚举值即可。

@{
    UserPromotion promo = UserPromotion.SendJobOffersByMail;
}

Promotion: @promo.GetDisplayName()

输出量

晋升:通过邮件发送工作机会


4
确保添加以下名称空间:using System; 使用System.ComponentModel.DataAnnotations; 使用System.Linq; 使用System.Reflection;
彼得·克尔

光滑的解决方案,但我得到{“模板只能与字段访问,属性访问,一维数组索引或单参数自定义索引器表达式一起使用。”}
Casey Crookston,2015年

查看此错误消息的其他SO答案(我不熟悉),似乎您可能是在Html帮助器方法中使用它(如@Html.DisplayFor(m => m.myEnum.GetDisplayName()),该方法将不起作用,因为他们希望所评估的表达式产生一个属性或类似的东西。您应该使用上面示例中的裸枚举值
Todd

7
我为结果添加了空引用检查,GetCustomAttribute<DisplayAttribute>()因为对于某些枚举,可能不存在。enumValue.ToString()如果不存在DisplayAttribute,则回退至此。
H狗

1
我用它来创建一个List<SelectListItem>由Enum填充的带有所有单独DisplayAttribute.Name注释的-效果很好,谢谢!! public List<SelectListItem> MySelectListItem = new List<SelectListItem>(); foreach (MyEnum MyEnum in Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Where(x => x != MyEnum.Default)) { MySelectListItem.Add(new SelectListItem() { Text = MyEnum.GetDisplayName(), Value = ((int)MyEnum).ToString() }); }
Hopper

61

根据Aydin的回答,我建议采用“重复性”较低的实现(因为我们可以轻松地TypeEnum值本身获取,而不是将其作为参数providing提供:

public static string GetDisplayName(this Enum enumValue)
{
    return enumValue.GetType().GetMember(enumValue.ToString())
                   .First()
                   .GetCustomAttribute<DisplayAttribute>()
                   .Name;
}

编辑(基于@Vahagn Nahapetyan的评论)

public static string GetDisplayName(this Enum enumValue)
{
    return enumValue.GetType()?
                    .GetMember(enumValue.ToString())?
                    .First()?
                    .GetCustomAttribute<DisplayAttribute>()?
                    .Name;
}

现在,我们可以通过这种方式非常干净地使用它:

public enum Season 
{
    [Display(Name = "The Autumn")]
    Autumn,

    [Display(Name = "The Weather")]
    Winter,

    [Display(Name = "The Tease")]
    Spring,

    [Display(Name = "The Dream")]
    Summer
}

Season.Summer.GetDisplayName();

导致

“梦想”


1
到目前为止,所有答案中最简单,最简单的。谢谢!
Casey Crookston

您应谨慎使用.First()。例如,如果您的枚举名称为“ Equals”,则会抛出异常
Vahagn Nahapetyan

我了解First()带来的“危险”。在这种特殊情况下,这似乎不是问题。因为它是扩展方法,所以其中this必须是有效的(非null)Enum值。否则,调用该方法将已经抛出(这是调用代码的责任)。这样GetType()就可以确保提供正确的枚举类型,并enumvalue可以肯定地成为其中的成员。但是GetCustomAttribute可能会返回null值,因此我提供了该方法的非异常版本,以在方法调用链在某处具有null返回值时返回null。谢谢!
Bernoulli IT

1
对于您的代码的第二个变体,似乎不需要在GetMember之后使用空条件运算符,因为此方法始终返回MemberInfo数组,而从不返回null。对我来说,似乎最好使用FirstOrDefault而不是First。然后,在FirstOrDefault之后使用null条件运算符将被视为一致。
Alex34758 '18

28

如果您使用的是MVC 5.1或更高版本,则有一种更简单明了的方法:只需使用数据注释(来自System.ComponentModel.DataAnnotations名称空间),如下所示:

public enum Color
{
    [Display(Name = "Dark red")]
    DarkRed,
    [Display(Name = "Very dark red")]
    VeryDarkRed,
    [Display(Name = "Red or just black?")]
    ReallyDarkRed
}

并且,将其放入适当的html帮助器中:

@Html.EnumDropDownListFor(model => model.Color)

@SegmentationFault为什么?你能描述你的问题吗?您使用哪个版本的.NET / MVC?你有什么错误?请更具体。
1_bug

6
因为它仅适用于下拉菜单,而不适用于其他任何地方。
分段故障

2
.net核心中似乎不存在
Lonefish'Jan

3
.net核心使用Html.GetEnumSelectList(typeof(YourEnum))@Lonefish
Patrick Mcvay

2
如果我们要使用@ Html.DisplayFor(yourEnumField),可以将Enum.cshtml放在DisplayTemplates目录(位于共享目录中)中。在此文件中,我们只需要放置2行。第一个是:“ @ model Enum”,第二个是:“ @ GetDisplayName(Model)”。GetDisplayName方法必须与@Bernoulli IT answare中一样
开发人员

11

您可以使用Type.GetMember方法,然后使用反射获取属性信息

// display attribute of "currentPromotion"

var type = typeof(UserPromotion);
var memberInfo = type.GetMember(currentPromotion.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false);
var description = ((DisplayAttribute)attributes[0]).Name;

这里有一些类似的帖子:

获取枚举值的属性

如何使MVC3 DisplayFor显示枚举的Display-Attribute的值?


8

建设托德最伟大的答案,其建立在艾登的伟大答案,这里有一个通用的,不需要任何类型的参数,扩展方法。

/// <summary>
/// Gets human-readable version of enum.
/// </summary>
/// <returns>DisplayAttribute.Name property of given enum.</returns>
public static string GetDisplayName<T>(this T enumValue) where T : IComparable, IFormattable, IConvertible
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("Argument must be of type Enum");

    DisplayAttribute displayAttribute = enumValue.GetType()
                                                 .GetMember(enumValue.ToString())
                                                 .First()
                                                 .GetCustomAttribute<DisplayAttribute>();

    string displayName = displayAttribute?.GetName();

    return displayName ?? enumValue.ToString();
}

我的项目需要这个,因为类似于下面的代码(其中不是每个枚举成员都有一个DisplayAttribute)都不适用于Todd的解决方案:

public class MyClass
{
    public enum MyEnum 
    {
        [Display(Name="ONE")]
        One,
        // No DisplayAttribute
        Two
    }
    public void UseMyEnum()
    {
        MyEnum foo = MyEnum.One;
        MyEnum bar = MyEnum.Two;
        Console.WriteLine(foo.GetDisplayName());
        Console.WriteLine(bar.GetDisplayName());
    }
}
// Output:
//
// ONE
// Two

如果这是对一个简单问题的复杂解决方案,请让我知道,但这是我使用的解决方法。


6
<ul>
    @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
    {
        var currentPromotion = (int)Model.JobSeeker.Promotion;
        if ((currentPromotion & aPromotion) == aPromotion)
        {
        <li>@Html.DisplayFor(e => currentPromotion)</li>
        }
    }
</ul>

不起作用:/我遇到错误InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
Muflix

6

对于这个问题,我有两种解决方案。

  1. 第一个解决方案是从枚举获取显示名称。
public enum CourseLocationTypes
{
    [Display(Name = "On Campus")]
    OnCampus,
    [Display(Name = "Online")]
    Online,
    [Display(Name = "Both")]
    Both
}

public static string DisplayName(this Enum value)
{
    Type enumType = value.GetType();
    string enumValue = Enum.GetName(enumType, value);
    MemberInfo member = enumType.GetMember(enumValue)[0];

    object[] attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
    string outString = ((DisplayAttribute)attrs[0]).Name;

    if (((DisplayAttribute)attrs[0]).ResourceType != null)
    {
        outString = ((DisplayAttribute)attrs[0]).GetName();
    }

    return outString;
}
<h3 class="product-title white">@Model.CourseLocationType.DisplayName()</h3>
  1. 第二个解决方案是从枚举名称中获取显示名称,但是将以开发人员语言的枚举拆分它,称为补丁。
public static string SplitOnCapitals(this string text)
{
        var r = new Regex(@"
            (?<=[A-Z])(?=[A-Z][a-z]) |
             (?<=[^A-Z])(?=[A-Z]) |
             (?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace);

        return r.Replace(text, " ");
}
 <div class="widget-box pt-0">
     @foreach (var item in Enum.GetNames(typeof(CourseLocationType)))
     {
         <label class="pr-2 pt-1">
             @Html.RadioButtonFor(x => x.CourseLocationType, item, new { type = "radio", @class = "iCheckBox control-label" })&nbsp; @item.SplitOnCapitals()
         </label>
     }
     @Html.ValidationMessageFor(x => x.CourseLocationType)
 </div>

5

对于ASP.Net Core 3.0,这对我有用(贷记给以前的答复者)。

我的Enum类:

using System;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

public class Enums
{
    public enum Duration
    { 
        [Display(Name = "1 Hour")]
        OneHour,
        [Display(Name = "1 Day")]
        OneDay
    }

    // Helper method to display the name of the enum values.
    public static string GetDisplayName(Enum value)
    {
        return value.GetType()?
       .GetMember(value.ToString())?.First()?
       .GetCustomAttribute<DisplayAttribute>()?
       .Name;
    }
}

我的视图模型类:

public class MyViewModel
{
    public Duration Duration { get; set; }
}

显示标签和下拉列表的剃刀视图的示例。请注意,下拉列表不需要帮助方法:

@model IEnumerable<MyViewModel> 

@foreach (var item in Model)
{
    <label asp-for="@item.Duration">@Enums.GetDisplayName(item.Duration)</label>
    <div class="form-group">
        <label asp-for="@item.Duration" class="control-label">Select Duration</label>
        <select asp-for="@item.Duration" class="form-control"
            asp-items="Html.GetEnumSelectList<Enums.Duration>()">
        </select>
    </div>
}

我会在GetDisplayName方法返回字符串上添加检查。IsNullOrEmpty(retVal)吗?enumValue.ToString():retVal;
Sniipe

4

您需要使用一些反射来访问该属性:

var type = typeof(UserPromotion);
var member = type.GetMember(Model.JobSeeker.Promotion.ToString());
var attributes = member[0].GetCustomAttributes(typeof(DisplayAttribute), false);
var name = ((DisplayAttribute)attributes[0]).Name;

我建议将此方法包装在扩展方法中或在视图模型中执行。


4

使用Core 2.1,

public static string GetDisplayName(Enum enumValue)
{
  return enumValue.GetType()?
 .GetMember(enumValue.ToString())?[0]?
 .GetCustomAttribute<DisplayAttribute>()?
 .Name;
}

4

从上方将所有边缘情况组合在一起:

  • 具有基本对象成员名称的枚举成员(EqualsToString
  • 可选Display属性

这是我的代码:

public enum Enum
{
    [Display(Name = "What a weird name!")]
    ToString,

    Equals
}

public static class EnumHelpers
{
    public static string GetDisplayName(this Enum enumValue)
    {
        var enumType = enumValue.GetType();

        return enumType
                .GetMember(enumValue.ToString())
                .Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == enumType)
                .First()
                .GetCustomAttribute<DisplayAttribute>()?.Name ?? enumValue.ToString();
    }
}

void Main()
{
    Assert.Equals("What a weird name!", Enum.ToString.GetDisplayName());
    Assert.Equals("Equals", Enum.Equals.GetDisplayName());
}

处理可选的Display属性的不错的解决方案。谢谢!
Wellspring

3

我很抱歉这样做,但是我不能按原样使用其他任何答案,也没有时间在评论中加以说明。

使用C#6语法。

static class EnumExtensions
{
    /// returns the localized Name, if a [Display(Name="Localised Name")] attribute is applied to the enum member
    /// returns null if there isnt an attribute
    public static string DisplayNameOrEnumName(this Enum value)
    // => value.DisplayNameOrDefault() ?? value.ToString()
    {
        // More efficient form of ^ based on http://stackoverflow.com/a/17034624/11635
        var enumType = value.GetType();
        var enumMemberName = Enum.GetName(enumType, value);
        return enumType
            .GetEnumMemberAttribute<DisplayAttribute>(enumMemberName)
            ?.GetName() // Potentially localized
            ?? enumMemberName; // Or fall back to the enum name
    }

    /// returns the localized Name, if a [Display] attribute is applied to the enum member
    /// returns null if there is no attribute
    public static string DisplayNameOrDefault(this Enum value) =>
        value.GetEnumMemberAttribute<DisplayAttribute>()?.GetName();

    static TAttribute GetEnumMemberAttribute<TAttribute>(this Enum value) where TAttribute : Attribute =>
        value.GetType().GetEnumMemberAttribute<TAttribute>(value.ToString());

    static TAttribute GetEnumMemberAttribute<TAttribute>(this Type enumType, string enumMemberName) where TAttribute : Attribute =>
        enumType.GetMember(enumMemberName).Single().GetCustomAttribute<TAttribute>();
}

2

进一步建立在Aydin和Todd的答案的基础上,这是一种扩展方法,该方法还允许您从资源文件中获取名称。

using AppResources;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Resources;

public static class EnumExtensions
{
    public static string GetDisplayName(this Enum enumValue)
    {
        var enumMember= enumValue.GetType()
                        .GetMember(enumValue.ToString());

        DisplayAttribute displayAttrib = null;
        if (enumMember.Any()) {
            displayAttrib = enumMember 
                        .First()
                        .GetCustomAttribute<DisplayAttribute>();
        }

        string name = null;
        Type resource = null;

        if (displayAttrib != null)
        {
            name = displayAttrib.Name;
            resource = displayAttrib.ResourceType;
        }

        return String.IsNullOrEmpty(name) ? enumValue.ToString()
            : resource == null ?  name
            : new ResourceManager(resource).GetString(name);
    }
}

并像这样使用

public enum Season 
{
    [Display(ResourceType = typeof(Resource), Name = Season_Summer")]
    Summer
}

我正在尝试让此项目适用于我的项目,但出现“ new ResourceManager(resource).GetString(name);”错误。线。我问了一个问题(stackoverflow.com/questions/31319251/…),我被送到这里。当我在运行时查看“ ResourceManager(resource)”时,它返回“ Resources.Enums.resource”。任何帮助将不胜感激。谢谢!
卡琳(Karinne)

未对某些枚举值设置显示名称时,更新了代码以更好地处理空值-可能会有所帮助
Peter Kerr

那仍然没有用。我使用错误消息更新了stackoverflow.com/questions/31319251/…上的问题。谢谢您的帮助!
卡琳妮

1

我想贡献与文化相关的GetDisplayName枚举扩展。希望这对以前像我这样搜索此答案的人有用:

正如Aydin AdnTodd提到的“标准”方式:

    public static string GetDisplayName(this Enum enumValue)
    {
        return enumValue
            .GetType()
            .GetMember(enumValue.ToString())
            .First()
            .GetCustomAttribute<DisplayAttribute>()
            .GetName();
    }

“与文化有关”的方式:

    public static string GetDisplayName(this Enum enumValue, CultureInfo ci)
    {
        var displayAttr = enumValue
            .GetType()
            .GetMember(enumValue.ToString())
            .First()
            .GetCustomAttribute<DisplayAttribute>();

        var resMan = displayAttr.ResourceType?.GetProperty(@"ResourceManager", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null, null) as ResourceManager;

        return resMan?.GetString(displayAttr.Name, ci) ?? displayAttr.GetName();
    }

1

2020更新:此线程中许多人提供的功能的更新版本,但现在从C#7.3起:

现在,您可以将通用方法限制为枚举类型,因此您可以编写一个方法扩展,以将其与所有枚举一起使用,如下所示:

通用扩展方法:

public static string ATexto<T>(this T enumeración) where T : struct, Enum {
    var tipo = enumeración.GetType();
    return tipo.GetMember(enumeración.ToString())
    .Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == tipo).First()
    .GetCustomAttribute<DisplayAttribute>()?.Name ?? enumeración.ToString();
} 

枚举:

public enum TipoImpuesto { 
IVA, INC, [Display(Name = "IVA e INC")]IVAeINC, [Display(Name = "No aplica")]NoAplica };

如何使用它:

var tipoImpuesto = TipoImpuesto.IVAeINC;
var textoTipoImpuesto = tipoImpuesto.ATexto(); // Prints "IVA e INC".

奖励,带有标志的枚举:如果您要处理普通的枚举,则上面的函数就足够了,但是如果您的任何枚举可以使用标志使用多个值,那么您将需要像这样修改它(此代码使用C#8特征):

    public static string ATexto<T>(this T enumeración) where T : struct, Enum {

        var tipo = enumeración.GetType();
        var textoDirecto = enumeración.ToString();

        string obtenerTexto(string textoDirecto) => tipo.GetMember(textoDirecto)
            .Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == tipo)
            .First().GetCustomAttribute<DisplayAttribute>()?.Name ?? textoDirecto;

        if (textoDirecto.Contains(", ")) {

            var texto = new StringBuilder();
            foreach (var textoDirectoAux in textoDirecto.Split(", ")) {
                texto.Append($"{obtenerTexto(textoDirectoAux)}, ");
            }
            return texto.ToString()[0..^2];

        } else {
            return obtenerTexto(textoDirecto);
        }

    } 

带有标志的枚举:

[Flags] public enum TipoContribuyente {
    [Display(Name = "Común")] Común = 1, 
    [Display(Name = "Gran Contribuyente")] GranContribuyente = 2, 
    Autorretenedor = 4, 
    [Display(Name = "Retenedor de IVA")] RetenedorIVA = 8, 
    [Display(Name = "Régimen Simple")] RégimenSimple = 16 } 

如何使用它:

var tipoContribuyente = TipoContribuyente.RetenedorIVA | TipoContribuyente.GranContribuyente;
var textoAux = tipoContribuyente.ATexto(); // Prints "Gran Contribuyente, Retenedor de IVA".

0

根据先前的答案,我创建了这个舒适的助手,以可读的方式支持所有DisplayAttribute属性:

public static class EnumExtensions
    {
        public static DisplayAttributeValues GetDisplayAttributeValues(this Enum enumValue)
        {
            var displayAttribute = enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttribute<DisplayAttribute>();

            return new DisplayAttributeValues(enumValue, displayAttribute);
        }

        public sealed class DisplayAttributeValues
        {
            private readonly Enum enumValue;
            private readonly DisplayAttribute displayAttribute;

            public DisplayAttributeValues(Enum enumValue, DisplayAttribute displayAttribute)
            {
                this.enumValue = enumValue;
                this.displayAttribute = displayAttribute;
            }

            public bool? AutoGenerateField => this.displayAttribute?.GetAutoGenerateField();
            public bool? AutoGenerateFilter => this.displayAttribute?.GetAutoGenerateFilter();
            public int? Order => this.displayAttribute?.GetOrder();
            public string Description => this.displayAttribute != null ? this.displayAttribute.GetDescription() : string.Empty;
            public string GroupName => this.displayAttribute != null ? this.displayAttribute.GetGroupName() : string.Empty;
            public string Name => this.displayAttribute != null ? this.displayAttribute.GetName() : this.enumValue.ToString();
            public string Prompt => this.displayAttribute != null ? this.displayAttribute.GetPrompt() : string.Empty;
            public string ShortName => this.displayAttribute != null ? this.displayAttribute.GetShortName() : this.enumValue.ToString();
        }
    }

0

我尝试将其作为编辑进行,但被拒绝了。我不明白为什么。

如果您使用混合了自定义属性和简单项目的Enum来调用上面的方法,则会抛出异常

public enum CommentType
{
    All = 1,
    Rent = 2,
    Insurance = 3,
    [Display(Name="Service Charge")]
    ServiceCharge = 4
}

因此,我对代码进行了少许修改,以便在尝试访问自定义属性之前先检查它们,并在找不到属性时使用该名称。

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumHelper<T>
{
    public static IList<T> GetValues(Enum value)
    {
        var enumValues = new List<T>();

        foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
        {
            enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
        }
        return enumValues;
    }

    public static T Parse(string value)
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }

    public static IList<string> GetNames(Enum value)
    {
        return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
    }

    public static IList<string> GetDisplayValues(Enum value)
    {
        return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
    }

    private static string lookupResource(Type resourceManagerProvider, string resourceKey)
    {
        foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
        {
            if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
            {
                System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
                return resourceManager.GetString(resourceKey);
            }
        }

        return resourceKey; // Fallback with the key name
    }

    public static string GetDisplayValue(T value)
    {
        var fieldInfo = value.GetType().GetField(value.ToString());

        var descriptionAttributes = fieldInfo.GetCustomAttributes(
            typeof(DisplayAttribute), false) as DisplayAttribute[];

        if (descriptionAttributes.Any() && descriptionAttributes[0].ResourceType != null)
            return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);

        if (descriptionAttributes == null) return string.Empty;
        return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
    }
}

0

使用MVC5,您可以使用:

public enum UserPromotion
{
   None = 0x0,

   [Display(Name = "Send Job Offers By Mail")]
   SendJobOffersByMail = 0x1,

   [Display(Name = "Send Job Offers By Sms")]
   SendJobOffersBySms = 0x2,

   [Display(Name = "Send Other Stuff By Sms")]
   SendPromotionalBySms = 0x4,

   [Display(Name = "Send Other Stuff By Mail")]
   SendPromotionalByMail = 0x8
}

然后,如果您想创建一个下拉选择器,则可以使用:

@Html.EnumDropdownListFor(expression: model => model.PromotionSelector, optionLabel: "Select") 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.