Ich verwende eine Erweiterungsmethode, um den Namen eines DisplayAttributes einer Enumeration abzurufen und in eine Combobox zu laden. Dies scheint ziemlich prozessorintensiv zu sein und die Leistung der Benutzeroberfläche wird beeinträchtigt.

Welche verschiedenen Möglichkeiten gibt es, einen Anzeigenamen für eine Aufzählung anzuzeigen?

Verlängerungsmethode, wenn Sie interessiert sind:

public static string GetDisplayName<T>(this T enumValue) where T : IComparable, IFormattable, IConvertible
{
    try
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<DisplayAttribute>()
                        .GetName();
    }
    catch // If there's no DisplayAttribute.Name set, just return the ToString value
    {
        return enumValue.ToString();
    }
}
2
Chris 17 Apr. 2018 im 22:26

4 Antworten

Beste Antwort

Cache die Werte im Grunde.

Zum Beispiel könnte ein static class EnumDisplayCache<T> einen statischen Konstruktor haben, der ein Dictionary<T, string> unter Verwendung Ihres Reflexionsansatzes und Enum.GetValues usw. mit einem:

public static bool GetDisplay(T value)
    => cache.TryGetValue(value, out name) ? name : value.ToString();

Dann wird Ihre Methode einfach:

return EnumDisplayCache<T>.GetDisplay(enumValue);
4
Marc Gravell 17 Apr. 2018 im 19:36

Hier finden Sie eine vollständige Implementierung einer Möglichkeit, eine Suche nach Aufzählungsnamen nur einmal pro Aufzählung und Anwendungslauf einzurichten. Da ein statischer Konstruktor verwendet wird, wird die Lookup-Map bei der ersten Verwendung für einen bestimmten Aufzählungstyp erstellt. Diese Implementierung behält die ursprünglich verwendete Erweiterungsmethode bei, die Implementierung verwendet jedoch die Suche nach zwischengespeicherten Namen.

// This class caches all value names for an enum the first time it is accessed
internal static class EnumNameCache<T> where T : struct, IComparable, IFormattable, IConvertible
{
    private static Dictionary<T, string> sNameMap;

    static EnumNameCache()
    {
        sNameMap = new Dictionary<T, string>();
        Type type = typeof(T);
        foreach (T value in Enum.GetValues(type).Cast<T>())
        {
            string valueName = value.ToString();
            sNameMap.Add(value, type.GetMember(valueName)[0].GetCustomAttribute<DisplayAttribute>()?.Name ?? valueName);
        }
    }

    public static string GetName(T value)
    {
        return sNameMap[value];
    }
}

// Contains extension methods for enums
internal static class EnumExtensions
{
    public static string GetDisplayName<T>(this T value) where T : struct, IComparable, IFormattable, IConvertible
    {
        return EnumNameCache<T>.GetName(value);
    }
}

// Example display attribute with a Name property because System.ComponentModel.DisplayNameAttribute cannot be used on enum values
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
internal class DisplayAttribute : Attribute
{
    public string Name { get; }
    public DisplayAttribute(string name)
    {
        Name = name;
    }
}

Wenn der Namenscache zum ersten Mal für eine bestimmte Aufzählung erstellt wird, wird es noch einige Überlegungen geben, aber danach werden die Suchvorgänge schnell durchgeführt. Beachten Sie, dass für das Attribut eine Nullprüfung anstelle eines Try / Catch-Blocks verwendet wird, da eine Nullprüfung schneller ist.

2
Xavier 17 Apr. 2018 im 21:15

Sie können Enum.GetNames(typeof(YourEnum)) ausprobieren, das ein string[] aller Namen in Ihrer Aufzählung zurückgibt.

0
na2axl 17 Apr. 2018 im 19:30

Sie können die .Resx-Datei verwenden und den Aufzählungsnamen als Standardanzeigenamen verwenden.

ResourceManager ist statisch und enthält Schlüsselwertobjekte. Wenn Sie den Schlüssel als Aufzählungsnamen und den Wert als Anzeigenamen angeben, können Sie den gewünschten Zeichenfolgenwert mit dem Aufzählungsnamen leicht erhalten

// StringResources is my ResourceManager object which is generated during adding .Resx file in solution
string displayname = GetName(MyEnum.SomeType.ToString(), StringResources)

public string GetName(string key, ResourceManager resourceManager)
{
    string displayName = resourceManager.GetString(key);
    if (string.IsNullOrEmpty(displayName))
        displayName = key;

    return displayName;
}
0
Adem Catamak 17 Apr. 2018 im 19:53