Enum 값의 속성 얻기


483

그 자체가 enum아닌 가치의 속성을 얻을 수 있는지 알고 싶습니다 enum. 예를 들어 다음이 있다고 가정합니다 enum.

using System.ComponentModel; // for DescriptionAttribute

enum FunkyAttributesEnum
{
    [Description("Name With Spaces1")]
    NameWithoutSpaces1,    
    [Description("Name With Spaces2")]
    NameWithoutSpaces2
}

내가 원하는 것은 열거 형 유형이 주어지고 2 튜플의 열거 형 문자열 값과 설명이 생성됩니다.

가치는 쉬웠다 :

Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
    Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);

그러나 설명 속성 값을 어떻게 얻 Tuple.Desc습니까? 속성이 enum자체에 속하는 경우 어떻게 해야하는지 생각할 수 있지만의 가치에서 얻는 방법에 대해서는 손실이 enum있습니다.



가능한 누구나
nawfal

2
설명에 필요한 네임 스페이스는 System.ComponentModel입니다.
John M

System.ComponentModel을 사용하지 않고 고유 한 속성 유형 만 사용할 수도 있습니다. 에 대한 특별한 것은 없습니다 DescriptionAttribute.
jrh

: plesae은이 링크를 참조 stackoverflow.com/a/58954215/5576498
AminGolmahalle

답변:


482

필요한 작업을 수행해야합니다.

var enumType = typeof(FunkyAttributesEnum);
var memberInfos = enumType.GetMember(FunkyAttributesEnum.NameWithoutSpaces1.ToString());
var enumValueMemberInfo = memberInfos.FirstOrDefault(m => m.DeclaringType == enumType);
var valueAttributes = 
      enumValueMemberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
var description = ((DescriptionAttribute)valueAttributes[0]).Description;

10
선택적으로 type.GetFields (BindingFlags.Public | BindingFlags.Static)를 사용하여 모든 memInfo를 한 번에 가져옵니다.
TrueWill

4
typeof (FunkyAttributesEnum)로 이동해야했지만 그 외에는 잘 작동했습니다. 감사.
Greg Randall

@AlexK Enum 클래스에 NameWithoutSpaces1 속성이 없습니다. FunkyAttributesEnum.NameWithoutSpaces1은 어디에서 왔습니까?
Don

2
@Don, OP의 질문에서 열거 형 멤버 이름입니다.
MEMark

287

이 코드는 일반 속성을 검색 할 수있는 열거 형에 멋진 확장 방법을 제공해야합니다. 사용하기가 간단하고 약간이기 때문에 위의 람다 함수와 다르다고 생각합니다. 일반 유형 만 전달하면됩니다.

public static class EnumHelper
{
    /// <summary>
    /// Gets an attribute on an enum field value
    /// </summary>
    /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
    /// <param name="enumVal">The enum value</param>
    /// <returns>The attribute of type T that exists on the enum value</returns>
    /// <example><![CDATA[string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;]]></example>
    public static T GetAttributeOfType<T>(this Enum enumVal) where T:System.Attribute
    {
        var type = enumVal.GetType();
        var memInfo = type.GetMember(enumVal.ToString());
        var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
        return (attributes.Length > 0) ? (T)attributes[0] : null;
    }
}

19
그러면 사용법은 다음과 같습니다. string desc = myEnumVariable.GetAttributeOfType <DescriptionAttribute> (). Description;
Brad Rem

2
사용법이 여기에 더 깨끗하기 때문에 (입력이 적기 때문에) +1 :)
nawfal

3
속성이 존재하지 않으면 IndexOutOfRangeException?
Erik Philips

6
enumVal.ToString ()이 다른 로케일에 대해 신뢰할 수 없으므로 memInfo에 type.GetMember (Enum.GetName (type, enumVal))을 사용하는 것이 좋습니다.
Lin Song Yang

2
호출의 요점은 무엇입니까 ? GetCustomAttributes()그러면 호출하는 대신 첫 번째 요소를 얻 GetCustomAttribute()습니까?
tigrou

81

이것은 선택을 위해 람다를 사용하는 일반적인 구현입니다.

public static Expected GetAttributeValue<T, Expected>(this Enum enumeration, Func<T, Expected> expression)
    where T : Attribute
{
    T attribute =
      enumeration
        .GetType()
        .GetMember(enumeration.ToString())
        .Where(member => member.MemberType == MemberTypes.Field)
        .FirstOrDefault()
        .GetCustomAttributes(typeof(T), false)
        .Cast<T>()
        .SingleOrDefault();

    if (attribute == null)
        return default(Expected);

    return expression(attribute);
}

다음과 같이 호출하십시오.

string description = targetLevel.GetAttributeValue<DescriptionAttribute, string>(x => x.Description);

4
대단하다. 주어진 열거 값이 조합 (으로 허용 FlagsAttribute) 인 경우 조심해야합니다 . 이 경우 enumeration.GetType().GetMember(enumeration.ToString())[0]실패합니다.
remio

가장 짧은 글을 쓸 수는 value.GetType().GetField(value.ToString()).GetCustomAttributes(false).OfType<T>‌​().SingleOrDefault()있지만 명시적인 방법을 인정해야합니다.
nawfal

2
또한 공개 정적 문자열 GetDescription (this Enum 열거)을 추가합니다. {return enumeration.GetAttributeValue <DescriptionAttribute, String> (x => x.Description); } 그 방법으로 그냥 targetLevel.GetDescription ();
MarkKGreenway

65

좀 더 확장 가능한 솔루션을 만들기 위해 여기에 몇 가지 답변을 병합했습니다. 앞으로 다른 사람에게 도움이 될 경우를 대비하여 제공하고 있습니다. 원래 게시물은 여기에 있습니다 .

using System;
using System.ComponentModel;

public static class EnumExtensions {

    // This extension method is broken out so you can use a similar pattern with 
    // other MetaData elements in the future. This is your base method for each.
    public static T GetAttribute<T>(this Enum value) where T : Attribute {
        var type = value.GetType();
        var memberInfo = type.GetMember(value.ToString());
        var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
        return attributes.Length > 0 
          ? (T)attributes[0]
          : null;
    }

    // This method creates a specific call to the above method, requesting the
    // Description MetaData attribute.
    public static string ToName(this Enum value) {
        var attribute = value.GetAttribute<DescriptionAttribute>();
        return attribute == null ? value.ToString() : attribute.Description;
    }

}

이 솔루션은 Enum에 확장 메소드 쌍을 만듭니다. 첫 번째는 리플렉션을 사용하여 값과 관련된 모든 속성을 검색 할 수 있습니다. 두 번째는 구체적으로 호출을 검색하여 값을 DescriptionAttribute반환합니다 Description.

예를 들어, DescriptionAttributefrom 속성을 사용해보십시오System.ComponentModel

using System.ComponentModel;

public enum Days {
    [Description("Sunday")]
    Sun,
    [Description("Monday")]
    Mon,
    [Description("Tuesday")]
    Tue,
    [Description("Wednesday")]
    Wed,
    [Description("Thursday")]
    Thu,
    [Description("Friday")]
    Fri,
    [Description("Saturday")]
    Sat
}

위의 확장 방법을 사용하려면 이제 다음을 호출하면됩니다.

Console.WriteLine(Days.Mon.ToName());

또는

var day = Days.Mon;
Console.WriteLine(day.ToName());

마지막 줄에서 "attribute.Description"을 의미합니까? return 속성 == null? value.ToString () : attribute.Description;
Jeson Martajaya

2
나는이 솔루션을 좋아하지만 거기에 버그가 있습니다. GetAttribute 메서드는 열거 형 값에 Description 특성이 있다고 가정하므로 특성 길이가 0 일 때 예외가 발생합니다. "return (T) attributes [0];" "return (attributes.Length> 0? (T) attributes [0] : null);"
Simon Gymer

@SimonGymer 제안에 감사드립니다-그에 따라 업데이트되었습니다. :)
Troy Alford

38

AdamCrawford response 외에도 설명을 얻기 위해 피드를 제공하는보다 특수한 확장 메서드를 만들었습니다.

public static string GetAttributeDescription(this Enum enumValue)
{
    var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>();
    return attribute == null ? String.Empty : attribute.Description;
} 

따라서 설명을 얻으려면 원래 확장 방법을 다음과 같이 사용할 수 있습니다.

string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description

또는 단순히 다음과 같이 확장 메소드를 호출 할 수 있습니다.

string desc = myEnumVariable.GetAttributeDescription();

희망적으로 코드를 좀 더 읽기 쉽게 만들어야합니다.


16

유창한 라이너 ...

여기서는 및 속성 DisplayAttribute이 모두 포함 된를 사용 Name하고 Description있습니다.

public static DisplayAttribute GetDisplayAttributesFrom(this Enum enumValue, Type enumType)
{
    return enumType.GetMember(enumValue.ToString())
                   .First()
                   .GetCustomAttribute<DisplayAttribute>();
}

public enum ModesOfTransport
{
    [Display(Name = "Driving",    Description = "Driving a car")]        Land,
    [Display(Name = "Flying",     Description = "Flying on a plane")]    Air,
    [Display(Name = "Sea cruise", Description = "Cruising on a dinghy")] Sea
}

void Main()
{
    ModesOfTransport TransportMode = ModesOfTransport.Sea;
    DisplayAttribute metadata = TransportMode.GetDisplayAttributesFrom(typeof(ModesOfTransport));
    Console.WriteLine("Name: {0} \nDescription: {1}", metadata.Name, metadata.Description);
}

산출

Name: Sea cruise 
Description: Cruising on a dinghy

2
나도 이것을 사용한다, 그것은 모든 대답 중에서 가장 깨끗하다! +1
Mafii

이것은 매우 유용한 것 같습니다! Thnx
Irf

7

다음은 Display 속성에서 정보를 얻는 코드입니다. 일반 메소드를 사용하여 속성을 검색합니다. 속성을 찾지 못하면 열거 형 값을 pascal / camel case를 title case로 변환 한 문자열로 변환합니다 ( 여기서 얻은 코드 )

public static class EnumHelper
{
    // Get the Name value of the Display attribute if the   
    // enum has one, otherwise use the value converted to title case.  
    public static string GetDisplayName<TEnum>(this TEnum value)
        where TEnum : struct, IConvertible
    {
        var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
        return attr == null ? value.ToString().ToSpacedTitleCase() : attr.Name;
    }

    // Get the ShortName value of the Display attribute if the   
    // enum has one, otherwise use the value converted to title case.  
    public static string GetDisplayShortName<TEnum>(this TEnum value)
        where TEnum : struct, IConvertible
    {
        var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
        return attr == null ? value.ToString().ToSpacedTitleCase() : attr.ShortName;
    }

    /// <summary>
    /// Gets an attribute on an enum field value
    /// </summary>
    /// <typeparam name="TEnum">The enum type</typeparam>
    /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
    /// <param name="value">The enum value</param>
    /// <returns>The attribute of type T that exists on the enum value</returns>
    private static T GetAttributeOfType<TEnum, T>(this TEnum value)
        where TEnum : struct, IConvertible
        where T : Attribute
    {

        return value.GetType()
                    .GetMember(value.ToString())
                    .First()
                    .GetCustomAttributes(false)
                    .OfType<T>()
                    .LastOrDefault();
    }
}

제목 케이스로 변환하기위한 문자열의 확장 방법입니다.

    /// <summary>
    /// Converts camel case or pascal case to separate words with title case
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static string ToSpacedTitleCase(this string s)
    {
        //https://stackoverflow.com/a/155486/150342
        CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
        TextInfo textInfo = cultureInfo.TextInfo;
        return textInfo
           .ToTitleCase(Regex.Replace(s, 
                        "([a-z](?=[A-Z0-9])|[A-Z](?=[A-Z][a-z]))", "$1 "));
    }

4

열거 형 값에서 설명을 얻기 위해이 확장 방법을 구현했습니다. 모든 종류의 열거 형에서 작동합니다.

public static class EnumExtension
{
    public static string ToDescription(this System.Enum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());
        var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}

동일한 솔루션의 일반 버전이 이미 게시되어 있습니다. 이모.
nawfal

4

열거 형에서 사전을 가져옵니다.

public static IDictionary<string, int> ToDictionary(this Type enumType)
{
    return Enum.GetValues(enumType)
    .Cast<object>()
    .ToDictionary(v => ((Enum)v).ToEnumDescription(), k => (int)k); 
}

이제 이렇게 불러

var dic = typeof(ActivityType).ToDictionary();

EnumDecription Ext 방법

public static string ToEnumDescription(this Enum en) //ext method
{
    Type type = en.GetType();
    MemberInfo[] memInfo = type.GetMember(en.ToString());
    if (memInfo != null && memInfo.Length > 0)
    {
        object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attrs != null && attrs.Length > 0)
            return ((DescriptionAttribute)attrs[0]).Description;
    }
    return en.ToString();
}

public enum ActivityType
{
    [Description("Drip Plan Email")]
    DripPlanEmail = 1,
    [Description("Modification")]
    Modification = 2,
    [Description("View")]
    View = 3,
    [Description("E-Alert Sent")]
    EAlertSent = 4,
    [Description("E-Alert View")]
    EAlertView = 5
}

3

다음은 System.Reflection.TypeExtensions를 사용하여 AdamCrawford의 답변의 .NET Core 버전입니다 .

public static class EnumHelper
{
    /// <summary>
    /// Gets an attribute on an enum field value
    /// </summary>
    /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
    /// <param name="enumVal">The enum value</param>
    /// <returns>The attribute of type T that exists on the enum value</returns>
    /// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
    public static T GetAttributeOfType<T>(this Enum enumVal) where T : System.Attribute
    {
        var type = enumVal.GetType();
        var memInfo = type.GetMember(enumVal.ToString());
        IEnumerable<Attribute> attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
        return (T)attributes?.ToArray()[0];
    }
}

.NET Core (또는 현재 Standard)에 GetMember가 있다고 생각하지 않으므로 이것이 어떻게 작동하는지 잘 모르겠습니다.
Jeff

System.Reflection.TypeExtensions에 있으며, 이것을 나열하기 위해 대답을 수정했습니다.
wonea

1
감사합니다 나는 약간의 확장 기능이 있다고 생각했다.
Jeff

3

Net Framework 및 NetCore에 대한 솔루션 추가

Net Framework 구현에 이것을 사용했습니다.

public static class EnumerationExtension
{
    public static string Description( this Enum value )
    {
        // get attributes  
        var field = value.GetType().GetField( value.ToString() );
        var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false );

        // return description
        return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found";
    }
}

NetCore에서는 작동하지 않으므로 다음과 같이 수정했습니다.

public static class EnumerationExtension
{
    public static string Description( this Enum value )
    {
        // get attributes  
        var field = value.GetType().GetField( value.ToString() );
        var attributes = field.GetCustomAttributes( false );

        // Description is in a hidden Attribute class called DisplayAttribute
        // Not to be confused with DisplayNameAttribute
        dynamic displayAttribute = null;

        if (attributes.Any())
        {
            displayAttribute = attributes.ElementAt( 0 );
        }

        // return description
        return displayAttribute?.Description ?? "Description Not Found";
    }
}

열거 형 예 :

public enum ExportTypes
{
    [Display( Name = "csv", Description = "text/csv" )]
    CSV = 0
}

정적 추가에 대한 샘플 사용법 :

var myDescription = myEnum.Description();

2

새로운 C # 언어 기능 중 일부를 활용하면 줄 수를 줄일 수 있습니다.

public static TAttribute GetEnumAttribute<TAttribute>(this Enum enumVal) where TAttribute : Attribute
{
    var memberInfo = enumVal.GetType().GetMember(enumVal.ToString());
    return memberInfo[0].GetCustomAttributes(typeof(TAttribute), false).OfType<TAttribute>().FirstOrDefault();
}

public static string GetEnumDescription(this Enum enumValue) => enumValue.GetEnumAttribute<DescriptionAttribute>()?.Description ?? enumValue.ToString();

2

이 답변은 열거 형 속성에서 콤보 상자를 설정하는 데 도움이되었습니다.

그런 다음 상자에서 선택 항목을 가져 와서 올바른 유형의 열거 형을 반환 할 수 있도록 역 코드를 작성해야했습니다.

또한 속성이 누락 된 경우를 처리하기 위해 코드를 수정했습니다.

다음 사람의 이익을 위해 여기에 나의 마지막 해결책이 있습니다.

public static class Program
{
   static void Main(string[] args)
    {
       // display the description attribute from the enum
       foreach (Colour type in (Colour[])Enum.GetValues(typeof(Colour)))
       {
            Console.WriteLine(EnumExtensions.ToName(type));
       }

       // Get the array from the description
       string xStr = "Yellow";
       Colour thisColour = EnumExtensions.FromName<Colour>(xStr);

       Console.ReadLine();
    }

   public enum Colour
   {
       [Description("Colour Red")]
       Red = 0,

       [Description("Colour Green")]
       Green = 1,

       [Description("Colour Blue")]
       Blue = 2,

       Yellow = 3
   }
}

public static class EnumExtensions
{

    // This extension method is broken out so you can use a similar pattern with 
    // other MetaData elements in the future. This is your base method for each.
    public static T GetAttribute<T>(this Enum value) where T : Attribute
    {
        var type = value.GetType();
        var memberInfo = type.GetMember(value.ToString());
        var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);

        // check if no attributes have been specified.
        if (((Array)attributes).Length > 0)
        {
            return (T)attributes[0];
        }
        else
        {
            return null;
        }
    }

    // This method creates a specific call to the above method, requesting the
    // Description MetaData attribute.
    public static string ToName(this Enum value)
    {
        var attribute = value.GetAttribute<DescriptionAttribute>();
        return attribute == null ? value.ToString() : attribute.Description;
    }

    /// <summary>
    /// Find the enum from the description attribute.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="desc"></param>
    /// <returns></returns>
    public static T FromName<T>(this string desc) where T : struct
    {
        string attr;
        Boolean found = false;
        T result = (T)Enum.GetValues(typeof(T)).GetValue(0);

        foreach (object enumVal in Enum.GetValues(typeof(T)))
        {
            attr = ((Enum)enumVal).ToName();

            if (attr == desc)
            {
                result = (T)enumVal;
                found = true;
                break;
            }
        }

        if (!found)
        {
            throw new Exception();
        }

        return result;
    }
}

}


1
나는 어리 석고 설명 할 수없는 많은 해결책을 보았고, 당신의 해결책은 그것을 죽였습니다. 감사합니다 <3
Kadaj

2

enum값이 포함되어 있으면 Equals여기에 많은 답변으로 일부 확장을 사용하여 몇 가지 버그가 발생할 수 있습니다. 이것은 정상적으로 가정 때문이다 typeof(YourEnum).GetMember(YourEnum.Value)는 IS 하나의 값을 반환 MemberInfo하여의를 enum. 다음은 Adam Crawford의 답변 보다 약간 더 안전한 버전 입니다.

public static class AttributeExtensions
{
    #region Methods

    public static T GetAttribute<T>(this Enum enumValue) where T : Attribute
    {
        var type = enumValue.GetType();
        var memberInfo = type.GetMember(enumValue.ToString());
        var member = memberInfo.FirstOrDefault(m => m.DeclaringType == type);
        var attribute = Attribute.GetCustomAttribute(member, typeof(T), false);
        return attribute is T ? (T)attribute : null;
    }

    #endregion
}

1

이 확장 메서드는 XmlEnumAttribute를 사용하여 열거 형 값의 문자열 표현을 가져옵니다. XmlEnumAttribute가 없으면 enum.ToString ()으로 폴백합니다.

public static string ToStringUsingXmlEnumAttribute<T>(this T enumValue)
    where T: struct, IConvertible
{
    if (!typeof(T).IsEnum)
    {
        throw new ArgumentException("T must be an enumerated type");
    }

    string name;

    var type = typeof(T);

    var memInfo = type.GetMember(enumValue.ToString());

    if (memInfo.Length == 1)
    {
        var attributes = memInfo[0].GetCustomAttributes(typeof(System.Xml.Serialization.XmlEnumAttribute), false);

        if (attributes.Length == 1)
        {
            name = ((System.Xml.Serialization.XmlEnumAttribute)attributes[0]).Name;
        }
        else
        {
            name = enumValue.ToString();
        }
    }
    else
    {
        name = enumValue.ToString();
    }

    return name;
}

1

그리고 전체 이름 목록을 원한다면 다음과 같이 할 수 있습니다

typeof (PharmacyConfigurationKeys).GetFields()
        .Where(x => x.GetCustomAttributes(false).Any(y => typeof(DescriptionAttribute) == y.GetType()))
        .Select(x => ((DescriptionAttribute)x.GetCustomAttributes(false)[0]).Description);

0

이것이 도움이된다면 내 솔루션을 공유 할 것입니다 : 사용자 정의 속성 정의 :

    [AttributeUsage(AttributeTargets.Field,AllowMultiple = false)]
public class EnumDisplayName : Attribute
{
    public string Name { get; private set; }
    public EnumDisplayName(string name)
    {
        Name = name;
    }
}

이제 HtmlHelper Extension의 HtmlHelper 정의 내부에 필요했기 때문에 :

public static class EnumHelper
{
    public static string EnumDisplayName(this HtmlHelper helper,EPriceType priceType)
    {
        //Get every fields from enum
        var fields = priceType.GetType().GetFields();
        //Foreach field skipping 1`st fieldw which keeps currently sellected value
        for (int i = 0; i < fields.Length;i++ )
        {
            //find field with same int value
            if ((int)fields[i].GetValue(priceType) == (int)priceType)
            {
                //get attributes of found field
                var attributes = fields[i].GetCustomAttributes(false);
                if (attributes.Length > 0)
                {
                    //return name of found attribute
                    var retAttr = (EnumDisplayName)attributes[0];
                    return retAttr.Name;
                }
            }
        }
        //throw Error if not found
        throw new Exception("Błąd podczas ustalania atrybutów dla typu ceny allegro");
    }
}

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


0
    public enum DataFilters
    {
        [Display(Name= "Equals")]
        Equals = 1,// Display Name and Enum Name are same 
        [Display(Name= "Does Not Equal")]
        DoesNotEqual = 2, // Display Name and Enum Name are different             
    }

이제이 경우 오류가 발생합니다. 1 "같음"

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

따라서 표시 이름과 열거 이름이 동일한 경우 enumMember.GetCustomAttribute ()가 null을 반환하므로 표시 이름이 아닌 반환 열거 이름이 동일한 경우 .....


0

또는 다음을 수행 할 수 있습니다.

List<SelectListItem> selectListItems = new List<SelectListItem>();

    foreach (var item in typeof(PaymentTerm).GetEnumValues())
    {
        var type = item.GetType();
        var name = type.GetField(item.ToString()).GetCustomAttributesData().FirstOrDefault()?.NamedArguments.FirstOrDefault().TypedValue.Value.ToString();
        selectListItems.Add(new SelectListItem(name, type.Name));

    }

0

이것이 .NET core 3.1과 함께 사용자 정의 도우미 또는 확장을 사용하지 않고 해결 한 방법입니다.

수업

public enum YourEnum
{
    [Display(Name = "Suryoye means Arameans")]
    SURYOYE = 0,
    [Display(Name = "Oromoye means Syriacs")]
    OROMOYE = 1,
}

면도칼

@using Enumerations

foreach (var name in Html.GetEnumSelectList(typeof(YourEnum)))
{
    <h1>@name.Text</h1>
}

1
'그것'을 해결 한 방법보다 더 많이 사용하여 질문에 대답하는 것을 고려하십시오. 문제를 인정하고 이것이 어떻게 '그것'을 해결한다고 생각하는지 설명하는 것으로 시작하십시오. 몇 년 후에는 당신의 대답이 맥락에서 벗어날 수 있다는 것을 기억하십시오. 그러면 그것은 거의 쓸모가 없을 것입니다. 여기에 더 많은 내용을 추가하고 컨텍스트를 추가하면 답변과 가능한 역사적 / 아카이브 관련성이
높아집니다.

0

성능 문제

더 나은 성능을 원한다면 다음과 같이하십시오.

public static class AdvancedEnumExtensions
{
    /// <summary>
    /// Gets the custom attribute <typeparamref name="T"/> for the enum constant, if such a constant is defined and has such an attribute; otherwise null.
    /// </summary>
    public static T GetCustomAttribute<T>(this Enum value) where T : Attribute
    {
        return GetField(value)?.GetCustomAttribute<T>(inherit: false);
    }

    /// <summary>
    /// Gets the FieldInfo for the enum constant, if such a constant is defined; otherwise null.
    /// </summary>
    public static FieldInfo GetField(this Enum value)
    {
        ulong u64 = ToUInt64(value);
        return value
            .GetType()
            .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
            .Where(f => ToUInt64(f.GetRawConstantValue()) == u64)
            .FirstOrDefault();
    }

    /// <summary>
    /// Checks if an enum constant is defined for this enum value
    /// </summary>
    public static bool IsDefined(this Enum value)
    {
        return GetField(value) != null;
    }

    /// <summary>
    /// Converts the enum value to UInt64
    /// </summary>
    public static ulong ToUInt64(this Enum value) => ToUInt64((object)value);

    private static ulong ToUInt64(object value)
    {
        switch (Convert.GetTypeCode(value))
        {
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
                return unchecked((ulong)Convert.ToInt64(value, CultureInfo.InvariantCulture));

            case TypeCode.Byte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Char:
            case TypeCode.Boolean:
                return Convert.ToUInt64(value, CultureInfo.InvariantCulture);

            default: throw new InvalidOperationException("UnknownEnumType");
        }
    }
}

왜 이것이 더 나은 성능을 발휘합니까?

내장 메소드는 모두 우리가 신경 쓰지 않는 많은 다른 코드를 실행 한다는 점 제외 하고는 이와 매우 유사한 코드를 사용하기 때문 입니다. C #의 Enum 코드는 일반적으로 매우 끔찍합니다.

위의 코드는 Linq로 수정되고 간소화되어 관심있는 비트 만 포함합니다.

내장 코드가 느린 이유는 무엇입니까?

Enum.ToString () -vs- Enum.GetName (..)에 대해 먼저

항상 후자를 사용하십시오. (또는 아래에서 더 명확 해 지듯이 더 나아지지는 않습니다.)

ToString ()은 후자를 내부적으로 사용하지만 플래그를 결합하거나 숫자를 인쇄하는 등 우리가 원하지 않는 많은 것들도 수행합니다. 우리는 열거 형 내부에 정의 된 상수에만 관심이 있습니다.

Enum.GetName은 모든 필드를 가져오고 모든 이름에 대한 문자열 배열을 만들고 모든 RawConstantValues에서 위의 ToUInt64를 사용하여 모든 값의 UInt64 배열을 만들고 UInt64 값에 따라 두 배열을 정렬하고 마지막으로 이름을 가져옵니다. UInt64-array에서 BinarySearch를 수행하여 원하는 값의 인덱스를 찾아 이름 배열.

... 그런 다음 필드를 버리고 정렬 된 배열은 해당 이름을 사용하여 필드를 다시 찾습니다.

한마디 : "아!"


-1

또는 다음을 수행 할 수 있습니다.

Dictionary<FunkyAttributesEnum, string> description = new Dictionary<FunkyAttributesEnum, string>()
    {
      { FunkyAttributesEnum.NameWithoutSpaces1, "Name With Spaces1" },
      { FunkyAttributesEnum.NameWithoutSpaces2, "Name With Spaces2" },
    };

그리고 다음과 같이 설명을 얻으십시오.

string s = description[FunkyAttributesEnum.NameWithoutSpaces1];

제 생각에는 이것은 성찰이 필요하지 않기 때문에 당신이 성취하고자하는 일을하는보다 효율적인 방법입니다.


2
물론, 사람들이 생각하는 것만 큼 반성이 나쁘지는 않습니다.
Bryan Rowe

나쁘지 않다는 말은 항상 사용합니다. 그러나 종종 불필요하게 사용됩니다. :)
Ian P

44
이 솔루션은 설명을 열거 형 자체에서 멀어지게하여 적어도 두 가지 큰 문제를 만듭니다. 먼저 누군가가 새로운 열거 형 상수를 추가하면 다른 장소로 이동하여 항목을 추가해야합니다. 속성은 관리자가 수행해야 할 작업을 명확하게 표시합니다. 내 두 번째 문제는 코드가 훨씬 많다는 것입니다. 속성은 간결합니다.
scobi

1
@scott 그러나 그것은 당신이 당신의 자신의 순서를 지정할 수있게 하고 내가 실제로 원하는 거의 항상 표시하고 싶지 않은 값을 제외시킵니다.
Simon_Weaver

-2

또한 enum 값을 정의 할 수 있으며 Name_Without_Spaces, 설명을 원할 때 Name_Without_Spaces.ToString().Replace('_', ' ')밑줄을 공백으로 바꾸는 데 사용할 수 있습니다.


8
이것은 매우 우아하지 않은 솔루션입니다. @Bryan
Johann
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.