Enum'un değerinin niteliklerini alma


483

Kendisinin enumdeğil , değerlerin niteliklerini almanın mümkün olup olmadığını bilmek ister miyim enum? Örneğin, aşağıdakilere sahip olduğumu varsayalım enum:

using System.ComponentModel; // for DescriptionAttribute

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

Ne istediğim numaralandırma türü verilir, numaralandırma dize değeri ve açıklaması 2-tuples üretmek.

Değer kolaydı:

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

Ancak, doldurmak için description özelliğinin değerini nasıl alabilirim Tuple.Desc? Özniteliğin enumkendisine ait olması durumunda bunu nasıl yapacağımı düşünebilirim , ancak değerini nasıl alacağım konusunda bir kayıptayım enum.




2
Açıklama için gereken ad alanı System.ComponentModel
John M

Ayrıca System.ComponentModel'i ve kendi öznitelik türünüzü kullanamazsınız; gerçekten özel olan hiçbir şey yok DescriptionAttribute.
jrh

plesae bu bağlantıya bakın: stackoverflow.com/a/58954215/5576498
AminGolmahalle

Yanıtlar:


482

Bu ihtiyacınız olanı yapmalı.

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
İsteğe bağlı olarak tüm memInfos'ları bir kerede almak için type.GetFields (BindingFlags.Public | BindingFlags.Static) öğesini kullanın.
TrueWill

4
Ben typeof (FunkyAttributesEnum) gitmek zorunda kaldı, ama bunun dışında iyi çalıştı. Teşekkürler.
Greg Randall

@AlexK Enum sınıfının bir NameWithoutSpaces1 özelliği olduğunu görmüyorum. FunkyAttributesEnum.NameWithoutSpaces1 nereden geliyor?
Don

2
@Don, OP'nin sorusundaki enum üye adı.
MEMark

287

Bu kod parçası, genel bir öznitelik almanızı sağlayan herhangi bir numarada size güzel bir küçük uzantı yöntemi vermelidir. Yukarıdaki lambda işlevinden farklı olduğuna inanıyorum çünkü kullanımı daha basit ve hafif - sadece genel türden geçmeniz gerekiyor.

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
Kullanım daha sonra şöyle olur: string desc = myEnumVariable.GetAttributeOfType <DescriptionAttribute> () .Description;
Brad Rem

2
Bunu Scott'ınkinden daha çok seviyorum, çünkü kullanım burada daha az temiz (daha az yazarak), bu yüzden +1 :)
nawfal

3
Hiçbir öznitelik yoksa, bu bir atmaz IndexOutOfRangeExceptionmı?
Erik Philips

6
enumVal.ToString () olarak memInfo için type.GetMember (Enum.GetName (type, enumVal)) kullanın, farklı yerel ayarlar için güvenilir olmayabilir.
Lin Song Yang

2
Çağırma amacı nedir GetCustomAttributes()o zaman ilk elemanı almak yerine çağıran GetCustomAttribute()?
tigrou

81

Bu, seçim için bir lambda kullanan genel bir uygulamadır

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

Buna şöyle deyin:

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

4
Bu harika. Verilen numaralandırma değeri bir kombinasyonsa (izin verdiği şekilde) dikkatli olmalıyız FlagsAttribute. Bu durumda enumeration.GetType().GetMember(enumeration.ToString())[0]başarısız olur.
remio

Yazabileceğiniz en kısa şey:, value.GetType().GetField(value.ToString()).GetCustomAttributes(false).OfType<T>‌​().SingleOrDefault()ancak açık yolunuzu itiraf etmek daha iyidir.
nawfal

2
Ayrıca genel statik String GetDescription (bu Numaralandırma numaralandırma) {return enumeration.GetAttributeValue <DescriptionAttribute, String> (x => x.Description); } bu şekilde onun sadece targetLevel.GetDescription ();
MarkKGreenway

65

Biraz daha genişletilebilir bir çözüm oluşturmak için birkaç cevabı burada birleştirdim. İleride başkalarına yardımcı olması durumunda sağlıyorum. Orijinal yayın burada .

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

}

Bu çözüm, Enum üzerinde bir çift uzantı yöntemi oluşturur. Birincisi, değerinizle ilişkili herhangi bir niteliği almak için yansımayı kullanmanıza izin verir. İkincisi özellikle çağrılar değerini alır DescriptionAttributeve Descriptiondeğerini döndürür .

Örnek olarak, şu DescriptionAttributeözellikten yararlanın: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
}

Yukarıdaki uzantı yöntemini kullanmak için şimdi aşağıdakileri aramanız yeterlidir:

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

veya

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

Son satırda "öznitelik.Tanımı" mı demek istediniz? return niteliği == null? value.ToString (): attribute.Description;
Jeson Martajaya

2
Bu çözümü seviyorum, ama içinde bir hata var. GetAttribute yöntemi, enum değerinin bir Description özniteliğine sahip olduğunu varsayar ve bu nedenle öznitelik uzunluğu 0 olduğunda bir istisna atar. "Return (T) nitelikleri [0];" "return (attributes.Length> 0? (T) nitelikleri [0]: null);"
Simon Gymer

@SimonGymer öneri için teşekkürler - Ben buna göre güncelledim. :)
Troy Alford

38

AdamCrawford yanıtına ek olarak , açıklamayı almak için onu besleyen daha özel bir uzantı yöntemleri oluşturdum.

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

dolayısıyla, açıklamayı almak için orijinal uzantı yöntemini şu şekilde kullanabilirsiniz:

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

veya burada uzantı yöntemini şu şekilde çağırabilirsiniz:

string desc = myEnumVariable.GetAttributeDescription();

Umarım kodunuzu biraz daha okunabilir hale getirir.


16

Akıcı bir astar ...

Burada DisplayAttributehem Nameve Descriptionözelliklerini içeren kullanıyorum .

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

Misal

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

Çıktı

Name: Sea cruise 
Description: Cruising on a dinghy

2
Bunu da kullanıyorum, tüm cevapların en temizi! +1
Mafii

Bu oldukça faydalı görünüyor! Thnx
IRF

7

İşte bir Display özelliğinden bilgi almak için kod. Özniteliği almak için genel bir yöntem kullanır. Öznitelik bulunmazsa, enum değerini başlık büyüklüğüne dönüştürülen pascal / camel büyüklüğüne sahip bir dizeye dönüştürür (kod burada elde edilir )

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

Ve bu, başlık durumuna dönüştürmek için dizeler için genişletme yöntemidir:

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

Enum değerlerinden açıklama almak için bu uzantı yöntemini uyguladım. Her tür numaralandırma için çalışır.

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

aynı çözümün genel sürümü zaten yayınlanmıştır. imo, daha iyi.
nawfal

4

Sözlüğü enum'dan al.

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

Şimdi buna şöyle deyin ...

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

EnumDecription Ext Yöntemi

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

İşte System.Reflection.TypeExtensions kullanarak AdamCrawford'ın cevabının .NET Core sürümü ;

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

Ben .NET Core (ya da daha doğrusu, Standart şimdi) GetMember olduğuna inanmıyorum bu yüzden nasıl çalışacağından emin değilim.
Jeff

System.Reflection.TypeExtensions içinde, bunu listelemek için cevabımı gözden geçirdim.
wonea

1
Yakaladım, teşekkürler. Oyunda bazı uzantılar olabileceğini düşündüm.
Jeff

3

Net Framework ve NetCore için çözümümü ekliyorum.

Bunu Net Framework uygulamam için kullandım:

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

Bu NetCore için çalışmaz, bu yüzden bunu yapmak için değiştirildi:

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

Numaralandırma Örneği:

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

Her iki statik için de örnek kullanım:

var myDescription = myEnum.Description();

2

Bazı yeni C # dil özelliklerinden yararlanarak satır sayısını azaltabilirsiniz:

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

Ben büyük bir numaralandırma özniteliklerinden bir açılan kutu ayarlamak için bu cevabı.

Sonra kutudan seçimi almak ve enum doğru tipte geri böylece ters kodlamak gerekiyordu.

Ayrıca bir özniteliğin eksik olduğu durumu işlemek için kodu değiştirdim

Bir sonraki kişinin yararları için, son çözümüm burada

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
Adamım çok aptalca ve açıklanamayan çözümler gördüm ve sizinkini öldürdünüz. Seni çok <3 Teşekkür
Kadaj

2

Sizin enumdeğeriniz sizin gibi bir değer içeriyorsa, Equalsburada birçok cevapta bazı uzantıları kullanarak birkaç hataya çarpabilirsiniz. Bunun nedeni, normalde typeof(YourEnum).GetMember(YourEnum.Value)yalnızca MemberInfosizin için bir değer döndüreceği varsayılır enum. İşte Adam Crawford'un cevabı biraz daha güvenli bir versiyon .

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

Bu uzantı yöntemi, XmlEnumAttribute öğesini kullanarak bir enum değerinin dize olarak temsilini alır. Hiçbir XmlEnumAttribute yoksa, enum.ToString () öğesine geri döner.

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

Ve isimlerin tam listesini istiyorsanız aşağıdaki gibi bir şey yapabilirsiniz

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

0

Çocuklar yardımcı oluyorsa sizinle çözümümü paylaşacağım: Özel özellik tanımı:

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

Şimdi HtmlHelper Uzantısı HtmlHelper tanımı içinde gerekli çünkü:

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

Umarım yardımcı olur


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             
    }

Şimdi bu durumda hata üretecek 1 "Eşittir"

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

Bu nedenle, enumMember.GetCustomAttribute (), görünen ad ve enum ad aynı ise, görünen ad yerine aynı enum adını döndürürse .....


0

Alternatif olarak, aşağıdakileri yapabilirsiniz:

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 ile özel yardımcılar veya uzantılar kullanmadan bu şekilde çözdüm.

Sınıf

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

Ustura

@using Enumerations

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

1
soruyu 'nasıl' çözdüğünüzden daha fazlasını kullanarak cevaplamayı düşünün - sorunu kabul ederek ve bunun 'onu' çözdüğünü nasıl düşündüğünüzü açıklayarak başlayın. Unutmayın, cevabınız bundan birkaç yıl sonra bağlam dışına çıkarılabilir ve o zaman neredeyse işe yaramaz olacaktır. Daha fazlasını eklemek, bir bağlam eklemek cevabınızı ve olası tarihsel / arşiv alaka düzeyini
yükseltir

0

Performans önemlidir

Daha iyi performans istiyorsanız, bu yol:

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

Bunun performansı neden daha iyi?

Çünkü yerleşik yöntemlerin hepsi buna çok benzer kod kullanırlar , ancak umursadığımız bir sürü başka kod çalıştırırlar . C # Enum kodu genel olarak oldukça korkunç.

Yukarıdaki kod Linq-ified ve aerodinamik hale getirilmiştir, bu yüzden sadece önem verdiğimiz bitleri içerir.

Dahili kod neden yavaş?

Enum.ToString () -vs- Enum.GetName (..) ile ilgili ilk

Daima ikincisini kullanın. (Ya da daha iyisi, aşağıda da anlaşılacağı gibi).

ToString (), ikincisini dahili olarak kullanır, ancak yine, istemediğimiz bir sürü başka şey de yapar, örneğin bayrakları birleştirmeye, sayıları yazdırmaya çalışır vb.

Enum.GetName sırayla tüm alanları alır, tüm adlar için bir dize dizisi oluşturur, tüm ToCIntant64 değerlerini tüm RawConstantValues ​​değerinde kullanır ve tüm değerlerin bir UInt64 dizisini oluşturur, her iki diziyi de UInt64 değerine göre sıralar ve son olarak UInt64 dizisinde bir BinarySearch yaparak istediğimiz değerin dizinini bulmak için name-array.

... sonra alanları atıyoruz ve sıralı diziler, alanı yeniden bulmak için bu ismi kullanıyor.

Tek kelime: "Ah!"


-1

Alternatif olarak, aşağıdakileri yapabilirsiniz:

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

Ve aşağıdakileri içeren açıklamayı alın:

string s = description[FunkyAttributesEnum.NameWithoutSpaces1];

Bence bu, yansıtmak gerekmediği için, başarmak istediğiniz şeyi yapmanın daha etkili bir yoludur.


2
Tabii, ama yansıma insanlar bunu yapmak kadar kötü değil.
Bryan Rowe

Kötü olduğunu söylemiyorum - her zaman kullanıyorum. Yine de çoğu zaman gereksiz yere kullanılır. :)
Ian P

44
Bu çözüm en az iki büyük sorun yaratarak tanımı numaralandırmanın kendisinden uzaklaştırır. Birincisi, birisi yeni bir numaralandırma sabiti eklerse, oraya bir giriş eklemek için bu yere gitmeyi bilmeleri gerekir. Nitelikler, bir bakıcıya ne yapmaları gerektiğinin açık bir işaretidir. İkinci sorunum sadece daha fazla kod olması. Öznitelikler kompakttır.
scobi

1
@scott, ancak kendi siparişinizi belirtmenize ve görüntülemek istemediğiniz değerleri hariç tutmanıza izin verir, bu da neredeyse her zaman istediğim şeydir
Simon_Weaver

-2

Ayrıca bir numaralandırma değeri tanımlayabilirsiniz Name_Without_Spacesve açıklama istediğinizde Name_Without_Spaces.ToString().Replace('_', ' ')alt çizgileri boşluklarla değiştirmek için kullanın .


8
Bu çok beceriksiz bir çözüm. @Bryan
Johann
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.