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을 만들 수 있기를 원합니다. 이것은 지금까지 내가 한 일이지만 문제는 여기서 표시 이름을 어떻게 얻을 수 있습니까?

<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

10
더 명확하게하려면 : System.ComponentModel.DataAnnotations.DisplayAttribute. 아닙니다 System.ComponentModel.DisplayNameAttribute.
— kamranicus

1
여기에는 리플렉션 사용이 포함되어 성능에 영향을 줍니까? 'cos 이것은 많은 시간이라고 불릴 것입니다.
— Nico

답변:


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

value.GetType (). GetField (value.ToString ())은 내가 찾던 것입니다!
— cdie

이 대답은 null 검사가 추가 되어도 괜찮지 만 dotfuscation을 사용하지 않으면 stackoverflow.com/a/4412730/852806 의 대답 이 더 간단 해 보입니다.
— HockeyJ

5
에서 GetDisplayValue먼저 테스트해야합니다 descriptionAttributes == null당신은 배열에 액세스하기 전에 : descriptionAttributes[0]. 그렇지 않으면 예외가 발생할 수 있으며 null을 확인하는 아래 줄은 절대 적용되지 않습니다.
— Robert S.

미성년자 변경을 제안합니다. public static IList <T> GetValues ​​(Enum value)는 public static IList <T> GetValues ​​(T value) 일 수 있습니다. EnumHelper <T> ~ => 공개 정적 클래스 EnumHelper <T> 여기서 T : struct, IConvertible. 정적 구조자일까요? static EnumHelper () {if (! typeof (T) .IsEnum) {throw new ArgumentException ( "T는 열거 된 유형이어야합니다"); }}
— 톰

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>끔찍한 명명 규칙은 어떻습니까? 지정한 속성을 검색하고 모든 퍼블릭 메소드와 마찬가지로 파스칼 케이스를 사용합니다.
— 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();
    }
}

참고 : Name 속성 대신 GetName ()을 사용해야합니다. 이렇게하면 ResourceType 속성 속성을 사용하는 경우 지역화 된 문자열이 반환됩니다.

예

그것을 사용하려면보기에서 열거 형 값을 참조하십시오.

@{
    UserPromotion promo = UserPromotion.SendJobOffersByMail;
}

Promotion: @promo.GetDisplayName()

산출

프로모션 : 우편으로 구인 보내기


4
다음 네임 스페이스를 추가해야합니다. using System; System.ComponentModel.DataAnnotations 사용; System.Linq 사용; System.Reflection 사용;
— 피터 커

슬릭 솔루션은,하지만 난 { "템플릿은 필드 액세스, 속성 액세스, 단일 차원 배열 인덱스, 또는 단일 매개 변수를 사용자 정의 인덱서 표현을 사용할 수 있습니다."} 얻을
— 케이시 Crookston을

이 오류 메시지에 대한 다른 SO 답변을 살펴보면 (나는 익숙하지 @Html.DisplayFor(m => m.myEnum.GetDisplayName())않습니다) 평가 된 표현식이 속성을 산출하기를 기대하기 때문에 Html 도우미 메소드 내에서 이것을 사용할 수 있습니다 (예 : 작동하지 않음) 위의 예와 같이 bare 열거 형 값을 사용해야합니다
— Todd

7
GetCustomAttribute<DisplayAttribute>()일부 Enum의 경우 이것이 존재하지 않기 때문에 결과에 null 참조 검사를 추가했습니다 . enumValue.ToString()DisplayAttribute가 없으면 다시 폴백됩니다.
— H Dog

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의 답변을 바탕으로 덜 "중복적인"구현을 제안합니다 ( 파라미터로 제공하는 대신 값 자체 Type에서 쉽게 얻을 수 있기 때문에) Enum.

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 ()에주의해야합니다. 예를 들어 열거 이름이 "같음"인 경우 예외가 발생합니다.
— Vahagn Nahapetyan

First ()의 "위험"을 이해합니다. 이 특별한 경우에는 문제가되지 않습니다. this유효한 (Null이 아닌) Enum 값이어야 하는 확장 방법이기 때문에 . 그렇지 않으면 메소드 호출이 이미 발생합니다 (호출 코드의 책임 임). 이를 통해 멤버가 될 GetType()올바른 Enum Type을 제공 enumvalue할 수 있습니다. 그러나 GetCustomAttribute는 null 값을 반환 할 수 있으므로 메소드 호출 체인에 어딘가 null 반환 값이있을 때 예외가 아닌 버전의 메서드를 제공하여 null을 반환했습니다. 감사!
— Bernoulli IT

1
코드의 두 번째 변형에서는 GetMember 뒤에 null 조건부 연산자를 사용할 필요가없는 것 같습니다.이 메서드는 항상 MemberInfo의 배열을 반환하고 결코 null을 반환하지 않기 때문입니다. 그리고 나를 위해 First 대신 FirstOrDefault를 사용하는 것이 좋습니다. 그러면 FirstOrDefault 다음에 null 조건부 연산자를 사용하는 것이 일관된 것으로 나타납니다.
— Alex34758

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

3
.net 코어는 Html.GetEnumSelectList (typeof (YourEnum)) @Lonefish
— Patrick Mcvay를 사용합니다.

2
@ Html.DisplayFor (yourEnumField)를 사용하려면 DisplayTemplates 디렉토리 (공유 디렉토리)에 Enum.cshtml을 넣을 수 있습니다. 이 파일에서 우리는 단지 2 줄만 넣어야합니다. 첫 번째는 "@model Enum"이고 두 번째는 "@GetDisplayName (Model)"입니다. GetDisplayName 메소드는 @Bernoulli IT Answare
— Developer

11

Type.GetMember Method 를 사용한 다음 reflection을 사용하여 속성 정보 를 가져올 수 있습니다 .

// 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;

여기 비슷한 게시물이 몇 개있었습니다 :

Enum 값의 속성 얻기

MVC3 DisplayFor를 만드는 방법 Enum의 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();
}

열거 형의 모든 구성원이을 갖지 않는 아래 코드와 같은 것이 DisplayAttributeTodd의 솔루션과 작동하지 않기 때문에 프로젝트에 이것을 필요로했습니다 .

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

모든 엣지 케이스를 위에서 결합 :

  • 기본 개체 멤버 이름이있는 열거 형 멤버 ( Equals, ToString)
  • 선택 과목 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

열거 형 값 중 일부에 대해 표시 이름을 설정하지 않은 경우 null을보다 잘 처리하도록 코드가 업데이트되었습니다. – 도움이 될 수도 있습니다
— Peter Kerr

여전히 작동하지 않았습니다. stackoverflow.com/questions/31319251/…에 대한 질문을 오류 메시지로 업데이트했습니다 . 도와 주셔서 감사합니다!
— Karinne

1

문화권에 의존하는 GetDisplayName 열거 형 확장에 기여하고 싶습니다. 이것이 나처럼이 답변을 인터넷 검색하는 사람에게 유용 할 수 있기를 바랍니다.

Aydin Adn 과 Todd가 언급 한 "표준"방식 :

    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") 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.