wake-up-neo.com

Ermittelt die Aufzählung aus dem Aufzählungsattribut

Ich habe

public enum Als 
{
    [StringValue("Beantwoord")] Beantwoord = 0,
    [StringValue("Niet beantwoord")] NietBeantwoord = 1,
    [StringValue("Geselecteerd")] Geselecteerd = 2,
    [StringValue("Niet geselecteerd")] NietGeselecteerd = 3,
}

mit

public class StringValueAttribute : Attribute
{
    private string _value;

    public StringValueAttribute(string value)
    {
        _value = value;
    }

    public string Value
    {
        get { return _value; }
    }
}

Und ich möchte den Wert des ausgewählten Elements einer Combobox in ein int einfügen:

int i = (int)(Als)Enum.Parse(typeof(Als), (string)cboAls.SelectedValue); //<- WRONG

Ist das möglich und wenn ja, wie? (Die StringValue stimmt mit dem in der Combobox ausgewählten Wert überein.).

32
RubenHerman

Hier ist eine Hilfsmethode, die Sie in die richtige Richtung lenken sollte.

protected Als GetEnumByStringValueAttribute(string value)
{
    Type enumType = typeof(Als);
    foreach (Enum val in Enum.GetValues(enumType))
    {
        FieldInfo fi = enumType.GetField(val.ToString());
        StringValueAttribute[] attributes = (StringValueAttribute[])fi.GetCustomAttributes(
            typeof(StringValueAttribute), false);
        StringValueAttribute attr = attributes[0];
        if (attr.Value == value)
        {
            return (Als)val;
        }
    }
    throw new ArgumentException("The value '" + value + "' is not supported.");
}

Und um es zu nennen, machen Sie einfach Folgendes:

Als result = this.GetEnumByStringValueAttribute<Als>(ComboBox.SelectedValue);

Dies ist wahrscheinlich nicht die beste Lösung, da sie an Als gebunden ist und Sie diesen Code wahrscheinlich wiederverwendbar machen möchten. Was Sie wahrscheinlich wollen, um den Code aus meiner Lösung zu entfernen, um Ihnen den Attributwert zurückzugeben, und verwenden Sie dann einfach Enum.Parse, wie Sie es in Ihrer Frage tun.

21
djdd87

Ich verwende das DescriptionAttribute von Microsoft und die folgende Erweiterungsmethode:

public static string GetDescription(this Enum value)
{
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }

    string description = value.ToString();
    FieldInfo fieldInfo = value.GetType().GetField(description);
    DescriptionAttribute[] attributes =
       (DescriptionAttribute[])
     fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

    if (attributes != null && attributes.Length > 0)
    {
        description = attributes[0].Description;
    }
    return description;
}
11
Oliver

Hier sind ein paar Erweiterungsmethoden, die ich genau für diesen Zweck verwende. Ich habe diese umgeschrieben, um Ihre StringValueAttribute zu verwenden, aber wie Oliver verwende ich das DescriptionAttribute in meinem Code.

    public static T FromEnumStringValue<T>(this string description) where T : struct {
        Debug.Assert(typeof(T).IsEnum);

        return (T)typeof(T)
            .GetFields()
            .First(f => f.GetCustomAttributes(typeof(StringValueAttribute), false)
                         .Cast<StringValueAttribute>()
                         .Any(a => a.Value.Equals(description, StringComparison.OrdinalIgnoreCase))
            )
            .GetValue(null);
    }

Dies kann in .NET 4.5 etwas einfacher gestaltet werden:

    public static T FromEnumStringValue<T>(this string description) where T : struct {
        Debug.Assert(typeof(T).IsEnum);

        return (T)typeof(T)
            .GetFields()
            .First(f => f.GetCustomAttributes<StringValueAttribute>()
                         .Any(a => a.Value.Equals(description, StringComparison.OrdinalIgnoreCase))
            )
            .GetValue(null);
    }

Und um es zu nennen, machen Sie einfach Folgendes:

Als result = ComboBox.SelectedValue.FromEnumStringValue<Als>();

Umgekehrt , hier ist eine Funktion, um den String aus einem Enum-Wert zu erhalten:

    public static string StringValue(this Enum enumItem) {
        return enumItem
            .GetType()
            .GetField(enumItem.ToString())
            .GetCustomAttributes<StringValueAttribute>()
            .Select(a => a.Value)
            .FirstOrDefault() ?? enumItem.ToString();
    }

Und um es zu nennen:

string description = Als.NietBeantwoord.StringValue()
6
joshperry

Ich bin mir nicht sicher, ob ich hier etwas vermisse. Kannst du das nicht tun?

Als temp = (Als)combo1.SelectedItem;
int t = (int)temp;
1
theraneman

Wenn Sie von doppelten Links von dieser hoch gelobten Frage und Antwort ausgehen, finden Sie hier eine Methode, die mit der neuen Enum-Typ-Einschränkung von C # 7.3 funktioniert. Beachten Sie, dass Sie auch angeben müssen, dass es sich um eine struct handelt, damit Sie sie zum nullfähigen TEnum? machen können. Andernfalls wird eine Fehlermeldung angezeigt.

public static TEnum? GetEnumFromDescription<TEnum>(string description)
    where TEnum : struct, Enum 
{
    var comparison = StringComparison.OrdinalIgnoreCase;
    foreach (var field in typeof(TEnum).GetFields())
    {
        var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
        if (attribute != null)
        {
            if (string.Compare(attribute.Description, description, comparison) == 0)
                return (TEnum)field.GetValue(null);
        }
        if (string.Compare(field.Name, description, comparison) == 0)
            return (TEnum)field.GetValue(null);
    }
    return null;
}
1
DLeh

Ich habe eine mehr generische Lösung gemacht.
Sie können es mit jedem Attribut und sogar mit anderen Typen als string verwenden.

using System;

namespace EnumTest
{
    public static class EnumExtensions
    {
        #region Get enum from Attribute
        /// <summary>
        /// Searches the enum element which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
        /// Throws exception, if there is no enum element found which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
        /// </summary>
        /// <param name="attributeType">the type of the attribute. e.g. typeof(System.ComponentModel.DescriptionAttribute)</param>
        /// <param name="attributePropertyName">the property of the attribute to search. At DescriptionAttribute, this is "Description"</param>
        /// <param name="searchValue">the value to search</param>
        public static TEnum FromAttributeValueToEnum<TEnum>(Type attributeType, string attributePropertyName, object searchValue)
        where TEnum : struct, Enum
        {
            TEnum? result = FromAttributeValueToNullableEnum<TEnum>(attributeType, attributePropertyName, searchValue);

            if (result.HasValue)
            {
                return result.Value;
            }

            Type enumType = typeof(TEnum);
            throw new ArgumentException($"The enum type {enumType.FullName} has no element with a {attributeType.FullName} with {attributePropertyName} property equivalent to '{searchValue}'");
        }

        /// <summary>
        /// Searches the enum element which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
        /// Returns fallBackValue, if there is no enum element found which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
        /// </summary>
        /// <param name="attributeType">the type of the attribute. e.g. typeof(System.ComponentModel.DescriptionAttribute)</param>
        /// <param name="attributePropertyName">the property of the attribute to search. At DescriptionAttribute, this is "Description"</param>
        /// <param name="searchValue">the value to search</param> 
        public static TEnum FromAttributeValueToEnum<TEnum>(Type attributeType, string attributePropertyName, object searchValue, TEnum fallBackValue)
        where TEnum : struct, Enum
        {
            TEnum? result = FromAttributeValueToNullableEnum<TEnum>(attributeType, attributePropertyName, searchValue);

            if (result.HasValue)
            {
                return result.Value;
            }

            return fallBackValue;
        }

        /// <summary>
        /// Searches the enum element which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
        /// Returns null, if there is no enum element found which has a [attributeType] attribute with a attributePropertyName equivalent to searchValue.
        /// </summary>
        /// <param name="attributeType">the type of the attribute. e.g. typeof(System.ComponentModel.DescriptionAttribute)</param>
        /// <param name="attributePropertyName">the property of the attribute to search. At DescriptionAttribute, this is "Description"</param>
        /// <param name="searchValue">the value to search</param> 
        public static TEnum? FromAttributeValueToNullableEnum<TEnum>(Type attributeType, string attributePropertyName, object searchValue)
        where TEnum : struct, Enum
        {
            Type enumType = typeof(TEnum);
            if (!enumType.IsEnum)
            {
                throw new ArgumentException($"The type {enumType.FullName} is no Enum!");
            }

            if (attributeType == null)
            {
                throw new ArgumentNullException(nameof(attributeType));
            }

            if (!typeof(Attribute).IsAssignableFrom(attributeType))
            {
                throw new ArgumentException($"The type {attributeType.FullName} is no Attribute!", nameof(attributeType));
            }

            var propertyInfoAttributePropertyName = attributeType.GetProperty(attributePropertyName);

            if (propertyInfoAttributePropertyName == null)
            {
                throw new ArgumentException($"The type {attributeType.FullName} has no (public) property with name {attributePropertyName}", nameof(attributeType));
            }

            foreach (var field in enumType.GetFields())
            {
                var attribute = Attribute.GetCustomAttribute(field, attributeType);
                if (attribute == null)
                {
                    continue;
                }

                object attributePropertyValue = propertyInfoAttributePropertyName.GetValue(attribute);

                if (attributePropertyValue == null)
                {
                    continue;
                }

                if (attributePropertyValue.Equals(searchValue))
                {
                    return (TEnum)field.GetValue(null);
                }
            }

            return null;
        }
        #endregion
    }
}

@ RubenHermans erster Beitrag:

Als Beantwoord = EnumExtensions.FromAttributeValueToEnum<Als>(typeof(StringValueAttribute), nameof(StringValueAttribute.Value), "Beantwoord");

Erweitertes Beispiel:

public class IntValueAttribute : Attribute
{
    public IntValueAttribute(int value)
    {
        Value = value;
    }

    public int Value { get; private set; }
}

public enum EnumSample
{
    [Description("Eins")]
    [IntValue(1)]
    One,

    [Description("Zwei")]
    [IntValue(2)]
    Two,

    [Description("Drei")]
    [IntValue(3)]
    Three
}

EnumSample one = EnumExtensions.FromAttributeValueToEnum<EnumSample>(typeof(DescriptionAttribute), nameof(DescriptionAttribute.Description), "Eins");
EnumSample two = EnumExtensions.FromAttributeValueToEnum<EnumSample>(typeof(IntValueAttribute), nameof(IntValueAttribute.Value), 2);
0
Joseph K

Zum Parsen eines Zeichenfolgenwerts basierend auf Attributwerten, die auf Enum-Mitglieder angewendet wurden, empfehle ich die Verwendung meiner Enums.NET Open Source-Bibliothek.

Für ein benutzerdefiniertes Attribut wie die StringValueAttribute würden Sie dies tun.

Registrieren und speichern Sie eine benutzerdefinierte EnumFormat für StringValueAttribute.Value.

Format = Enums.RegisterCustomEnumFormat(m => m.Attributes.Get<StringValueAttribute>()?.Value);

Verwenden Sie dann die benutzerdefinierte EnumFormat.

Als result = Enums.Parse<Als>("Niet beantwoord", Format); // result == Als.NietBeantwoord

Wenn Sie stattdessen ein eingebautes Attribut wie DescriptionAttribute verwenden würden, könnten Sie dies einfach tun.

Als result = Enums.Parse<Als>("Niet beantwoord", EnumFormat.Description);

Wenn Sie interessiert sind, erhalten Sie auf diese Weise den Zeichenfolgenwert, der einem Aufzählungswert zugeordnet ist.

string value = Als.NietBeantwoord.AsString(Format); // value == "Niet beantwoord"
0
TylerBrinkley