Attribute des Enum-Werts abrufen


483

Ich würde gerne wissen, ob es möglich ist, Attribute der enumWerte und nicht der enumselbst zu erhalten. Angenommen, ich habe Folgendes enum:

using System.ComponentModel; // for DescriptionAttribute

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

Was ich möchte, ist der Aufzählungstyp, 2-Tupel des Aufzählungszeichenfolgenwerts und seine Beschreibung.

Wert war einfach:

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

Aber wie erhalte ich den Wert des Beschreibungsattributs zum Auffüllen Tuple.Desc? Ich kann mir überlegen, wie ich es machen soll, wenn das Attribut zu sich enumselbst gehört, aber ich bin ratlos, wie ich es aus dem Wert des machen kann enum.




2
Der für die Beschreibung erforderliche Namespace ist System.ComponentModel
John M

Sie können System.ComponentModel auch nicht verwenden und nur Ihren eigenen Attributtyp verwenden. Es gibt wirklich nichts Besonderes DescriptionAttribute.
jrh

Antworten:


482

Dies sollte tun, was Sie brauchen.

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
Verwenden Sie optional type.GetFields (BindingFlags.Public | BindingFlags.Static), um alle memInfos auf einmal abzurufen.
TrueWill

4
Ich musste typof gehen (FunkyAttributesEnum), aber ansonsten hat es gut funktioniert. Vielen Dank.
Greg Randall

@AlexK Ich sehe nicht, dass die Enum-Klasse eine NameWithoutSpaces1-Eigenschaft hat. Woher kommt die FunkyAttributesEnum.NameWithoutSpaces1?
Don

2
@Don, es ist der Name des Enum-Mitglieds aus der Frage des OP.
MEMark

287

Dieser Code sollte Ihnen eine nette kleine Erweiterungsmethode für jede Aufzählung geben, mit der Sie ein generisches Attribut abrufen können. Ich glaube, es unterscheidet sich von der obigen Lambda-Funktion, weil es einfacher und geringfügig zu verwenden ist - Sie müssen nur den generischen Typ übergeben.

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
Die Verwendung wäre dann: string desc = myEnumVariable.GetAttributeOfType <DescriptionAttribute> () .Description;
Brad Rem

2
Ich mag dieses mehr als das von Scott, weil die Verwendung hier sauberer ist (weniger Tippen), also +1 :)
nawfal

3
Wenn kein Attribut existiert, würde dies nicht ein werfen IndexOutOfRangeException?
Erik Philips

6
Verwenden Sie besser type.GetMember (Enum.GetName (type, enumVal)) für die memInfo, da enumVal.ToString () für verschiedene Gebietsschemas möglicherweise nicht zuverlässig ist.
Lin Song Yang

2
Was ist der Grund, aufzurufen und GetCustomAttributes()dann das erste Element zu erhalten, anstatt aufzurufen GetCustomAttribute()?
Tigrou

81

Dies ist eine generische Implementierung, bei der ein Lambda für die Auswahl verwendet wird

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

Nennen Sie es so:

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

4
Das ist toll. Wir müssen nur vorsichtig sein, wenn der angegebene Aufzählungswert eine Kombination ist (zulässig durch FlagsAttribute). In diesem Fall enumeration.GetType().GetMember(enumeration.ToString())[0]wird fehlschlagen.
Remio

Das kürzeste, was Sie schreiben könnten:, value.GetType().GetField(value.ToString()).GetCustomAttributes(false).OfType<T>‌​().SingleOrDefault()aber Sie müssen zugeben, dass Ihr expliziter Weg besser ist.
Nawfal

2
Ich füge auch einen öffentlichen statischen String hinzu. GetDescription (diese Enum-Aufzählung) {return enumeration.GetAttributeValue <DescriptionAttribute, String> (x => x.Description); } auf diese Weise ist es nur targetLevel.GetDescription ();
MarkKGreenway

65

Ich habe hier einige Antworten zusammengeführt, um eine etwas erweiterbarere Lösung zu erstellen. Ich biete es nur für den Fall an, dass es in Zukunft für andere hilfreich ist. Originalbeitrag hier .

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

}

Diese Lösung erstellt zwei Erweiterungsmethoden für Enum. Mit der ersten Option können Sie mithilfe der Reflexion alle mit Ihrem Wert verknüpften Attribute abrufen. Der zweite Aufruf ruft speziell das ab DescriptionAttributeund gibt seinen DescriptionWert zurück.

Verwenden Sie als Beispiel das DescriptionAttributeAttribut vonSystem.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
}

Um die obige Erweiterungsmethode zu verwenden, rufen Sie jetzt einfach Folgendes auf:

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

oder

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

In der letzten Zeile meinen Sie "attribute.Description"? Rückgabeattribut == null? value.ToString (): attribute.Description;
Jeson Martajaya

2
Ich liebe diese Lösung, aber es gibt einen Fehler darin. Die GetAttribute-Methode geht davon aus, dass der Enum-Wert ein Description-Attribut hat, und löst daher eine Ausnahme aus, wenn die Attributlänge 0 beträgt. Ersetzen Sie die "return (T) -Attribute [0];" mit "return (Attribute.Length> 0? (T) Attribute [0]: null);"
Simon Gymer

@ SimonGymer danke für den Vorschlag - ich habe entsprechend aktualisiert. :)
Troy Alford

38

Zusätzlich zur AdamCrawford-Antwort habe ich eine speziellere Erweiterungsmethode erstellt, die davon speist, um die Beschreibung zu erhalten.

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

Um die Beschreibung zu erhalten, können Sie daher entweder die ursprüngliche Erweiterungsmethode als verwenden

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

oder Sie können die Erweiterungsmethode hier einfach wie folgt aufrufen:

string desc = myEnumVariable.GetAttributeDescription();

Das sollte Ihren Code hoffentlich etwas lesbarer machen.


16

Fließender Einzeiler ...

Hier verwende ich das, DisplayAttributedas sowohl die Nameals auch die DescriptionEigenschaften enthält.

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

Beispiel

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

Ausgabe

Name: Sea cruise 
Description: Cruising on a dinghy

2
Ich benutze das auch, es ist die sauberste aller Antworten! +1
Mafii

Das scheint sehr nützlich zu sein! Danke
Irf

7

Hier ist Code zum Abrufen von Informationen aus einem Anzeigeattribut. Es verwendet eine generische Methode, um das Attribut abzurufen. Wenn das Attribut nicht gefunden wird, konvertiert es den Aufzählungswert in eine Zeichenfolge, wobei die Groß- / Kleinschreibung in die Groß- und Kleinschreibung konvertiert wird (Code hier erhalten ).

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

Dies ist die Erweiterungsmethode für Zeichenfolgen zum Konvertieren in Groß- und Kleinschreibung:

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

Ich habe diese Erweiterungsmethode implementiert, um die Beschreibung aus Enum-Werten zu erhalten. Es funktioniert für alle Arten von Aufzählungen.

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

Die generische Version derselben Lösung ist bereits veröffentlicht. imo, besser.
Nawfal

4

Holen Sie sich das Wörterbuch von enum.

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

Nennen Sie das jetzt wie ...

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

EnumDecription Ext-Methode

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

Hier ist die .NET Core-Version von AdamCrawfords Antwort unter Verwendung von System.Reflection.TypeExtensions .

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

Ich glaube nicht, dass .NET Core (oder besser gesagt Standard jetzt) ​​GetMember hat, daher bin ich mir nicht sicher, wie dies funktionieren würde.
Jeff

Es ist in System.Reflection.TypeExtensions, ich habe meine Antwort überarbeitet, um dies aufzulisten.
Wonea

1
Gotcha, danke. Ich dachte, es könnten einige Erweiterungen im Spiel sein.
Jeff

3

Hinzufügen meiner Lösung für Net Framework und NetCore.

Ich habe dies für meine Net Framework-Implementierung verwendet:

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

Dies funktioniert nicht für NetCore, daher habe ich es so geändert:

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

Aufzählungsbeispiel:

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

Beispielnutzung für beide statischen Elemente hinzugefügt:

var myDescription = myEnum.Description();

2

Mit einigen der neueren C # -Sprachenfunktionen können Sie die Zeilenanzahl reduzieren:

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

Ich habe diese Antwort gegeben, um ein Kombinationsfeld aus einem Enum-Attribut einzurichten, was großartig war.

Ich musste dann die Rückseite codieren, damit ich die Auswahl aus der Box erhalten und die Aufzählung im richtigen Typ zurückgeben kann.

Ich habe auch den Code geändert, um den Fall zu behandeln, in dem ein Attribut fehlte

Für die Vorteile der nächsten Person ist hier meine endgültige Lösung

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
Mann, ich habe so viele dumme und ungeklärte Lösungen gesehen, und deine haben es getötet. Vielen Dank <3
Kadaj

2

Wenn Ihr enumWert so ist, dass EqualsSie möglicherweise auf einige Fehler stoßen, indem Sie einige Erweiterungen in vielen Antworten verwenden. Dies liegt daran, dass normalerweise davon ausgegangen wird, dass typeof(YourEnum).GetMember(YourEnum.Value)nur ein Wert zurückgegeben wird, nämlich der MemberInfovon Ihnen enum. Hier ist eine etwas sicherere Version der Antwort von 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

Diese Erweiterungsmethode erhält eine Zeichenfolgendarstellung eines Aufzählungswerts unter Verwendung seines XmlEnumAttribute. Wenn kein XmlEnumAttribute vorhanden ist, wird auf enum.ToString () zurückgegriffen.

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

Und wenn Sie die vollständige Liste der Namen möchten, können Sie so etwas tun

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

0

Leute, wenn es hilft, werde ich meine Lösung mit Ihnen teilen: Definition des benutzerdefinierten Attributs:

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

Jetzt, weil ich es innerhalb der HtmlHelper-Definition der HtmlHelper-Erweiterung brauchte:

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

Ich hoffe es hilft


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             
    }

Jetzt wird in diesem Fall ein Fehler erzeugt. 1 "Gleich"

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

Wenn es also derselbe ist, wird der Aufzählungsname anstelle des Anzeigenamens zurückgegeben, da enumMember.GetCustomAttribute () null wird, wenn Anzeigename und Aufzählungsname identisch sind.


0

Alternativ können Sie Folgendes tun:

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

So habe ich es gelöst, ohne benutzerdefinierte Helfer oder Erweiterungen mit .NET Core 3.1 zu verwenden.

Klasse

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

Rasierer

@using Enumerations

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

1
Erwägen Sie, die Frage mit mehr als der Art und Weise zu beantworten, wie Sie "es" gelöst haben. Beginnen Sie damit, das Problem anzuerkennen und zu erklären, wie Sie denken, dass dies "es" löst. Denken Sie daran, dass Ihre Antwort in einigen Jahren aus dem Zusammenhang gerissen werden könnte und dann fast nutzlos wäre. Wenn Sie mehr hinzufügen und einen Kontext hinzufügen, wird Ihre Antwort und ihre mögliche historische / archivarische Relevanz
verbessert

0

Leistung ist wichtig

Wenn Sie eine bessere Leistung wünschen, ist dies der richtige Weg:

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

Warum hat dies eine bessere Leistung?

Da die integrierten Methoden alle Code verwenden, der diesem sehr ähnlich ist, außer dass sie auch eine Reihe anderer Codes ausführen, die uns egal sind . Der Enum-Code von C # ist im Allgemeinen ziemlich schrecklich.

Der obige Code wurde linearisiert und optimiert, sodass er nur die Bits enthält, die uns wichtig sind.

Warum ist der eingebaute Code langsam?

Zunächst zu Enum.ToString () -vs- Enum.GetName (..)

Verwenden Sie immer Letzteres. (Oder noch besser auch nicht, wie weiter unten deutlich wird.)

ToString () verwendet letzteres intern, erledigt aber auch eine Reihe anderer Dinge, die wir nicht wollen, z. B. Versuche, Flags zu kombinieren, Zahlen auszudrucken usw. Wir sind nur an Konstanten interessiert, die in der Aufzählung definiert sind.

Enum.GetName ruft wiederum alle Felder ab, erstellt ein String-Array für alle Namen, verwendet das obige ToUInt64 für alle RawConstantValues, um ein UInt64-Array aller Werte zu erstellen, sortiert beide Arrays nach dem UInt64-Wert und erhält schließlich den Namen von das Name-Array durch Ausführen einer BinarySearch im UInt64-Array, um den Index des gewünschten Werts zu finden.

... und dann werfen wir die Felder weg und die sortierten Arrays verwenden diesen Namen, um das Feld wieder zu finden.

Ein Wort: "Ugh!"


-1

Alternativ können Sie Folgendes tun:

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

Und erhalten Sie die Beschreibung mit folgendem:

string s = description[FunkyAttributesEnum.NameWithoutSpaces1];

Meiner Meinung nach ist dies eine effizientere Methode, um das zu tun, was Sie erreichen möchten, da keine Reflexion erforderlich ist.


2
Sicher, aber die Reflexion ist bei weitem nicht so schlecht, wie die Leute es sich vorstellen.
Bryan Rowe

Nicht sagen, dass es schlecht ist - ich benutze es die ganze Zeit. Es wird jedoch oft unnötig verwendet. :)
Ian P

44
Diese Lösung entfernt die Beschreibung von der Aufzählung selbst und verursacht mindestens zwei große Probleme. Wenn jemand eine neue Enum-Konstante hinzufügt, muss er zunächst wissen, dass er zu diesem anderen Ort gehen muss, um dort ebenfalls einen Eintrag hinzuzufügen. Attribute sind ein klares Zeichen für einen Betreuer dessen, was er tun muss. Mein zweites Problem dabei ist, dass es nur viel mehr Code ist. Attribute sind kompakt.
Scobi

1
@scott, aber es erlaubt Ihnen, Ihre eigene Reihenfolge anzugeben und Werte auszuschließen, die Sie nicht anzeigen möchten, was fast immer das ist, was ich eigentlich will
Simon_Weaver

-2

Sie können auch einen Aufzählungswert wie definieren. Name_Without_SpacesWenn Sie eine Beschreibung wünschen Name_Without_Spaces.ToString().Replace('_', ' '), können Sie die Unterstriche durch Leerzeichen ersetzen.


8
Dies ist eine sehr unelegante Lösung. Erwägen Sie die Verwendung der von @Bryan
Johann
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.