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