[C#] MVC 면도기 코드를 통해 Enum 멤버의 표시 이름 특성을 얻는 방법은 무엇입니까?

내 모델에 “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>



답변

최신 정보

첫 번째 솔루션은 열거 형에서 표시 이름을 얻는 데 중점을 두었습니다. 아래 코드는 문제에 대한 정확한 해결책입니다.

이 헬퍼 클래스를 열거 형에 사용할 수 있습니다.

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>

그것이 도움이되기를 바랍니다! 🙂


답변

하나의 라이너-유창한 구문

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);
    }
}

산출

어느 계절입니까?
여름이야


답변

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

산출

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


답변

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

어떤 결과

“그 꿈”


답변

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)


답변

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 값을 표시합니까?


답변

바탕 토드의 좋은 대답 을 기반으로 아이 딘의 큰 대답 , 여기의 일반적인 모든 유형의 매개 변수를 필요로하지 않는 확장 방법.

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

이것이 간단한 문제에 대한 복잡한 해결책이라면 알려주십시오. 그러나 이것은 내가 사용한 수정이었습니다.