J'ai
public enum Als
{
[StringValue("Beantwoord")] Beantwoord = 0,
[StringValue("Niet beantwoord")] NietBeantwoord = 1,
[StringValue("Geselecteerd")] Geselecteerd = 2,
[StringValue("Niet geselecteerd")] NietGeselecteerd = 3,
}
avec
public class StringValueAttribute : Attribute
{
private string _value;
public StringValueAttribute(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Et je voudrais mettre la valeur de l'élément que j'ai sélectionné d'une liste déroulante dans un int:
int i = (int)(Als)Enum.Parse(typeof(Als), (string)cboAls.SelectedValue); //<- WRONG
Est-ce possible, et si oui comment? (la StringValue
correspond à la valeur sélectionnée dans la liste déroulante).
Voici une méthode d'assistance qui devrait vous orienter dans la bonne direction.
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.");
}
Et pour l'appeler, procédez comme suit:
Als result = this.GetEnumByStringValueAttribute<Als>(ComboBox.SelectedValue);
Ce n'est probablement pas la meilleure solution car elle est liée à Als
et vous voudrez probablement rendre ce code réutilisable. Vous voudrez probablement supprimer le code de ma solution pour vous renvoyer la valeur de l'attribut, puis utilisez simplement Enum.Parse
comme vous le faites dans votre question.
J'utilise le DescriptionAttribute de Microsoft et la méthode d'extension suivante:
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;
}
Voici quelques méthodes d’extension que j’utilise dans ce but précis. Je les ai réécrites pour utiliser votre StringValueAttribute
, mais comme Oliver j’utilise le DescriptionAttribute dans mon 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);
}
Cela peut être légèrement simplifié dans .NET 4.5:
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);
}
Et pour l'appeler, procédez comme suit:
Als result = ComboBox.SelectedValue.FromEnumStringValue<Als>();
Inversement , voici une fonction pour obtenir la chaîne à partir d'une valeur enum:
public static string StringValue(this Enum enumItem) {
return enumItem
.GetType()
.GetField(enumItem.ToString())
.GetCustomAttributes<StringValueAttribute>()
.Select(a => a.Value)
.FirstOrDefault() ?? enumItem.ToString();
}
Et pour l'appeler:
string description = Als.NietBeantwoord.StringValue()
Je ne sais pas si quelque chose me manque ici, ne pouvez-vous pas le faire,
Als temp = (Als)combo1.SelectedItem;
int t = (int)temp;
En venant ici de liens en double de cette question et cette réponse très appréciées , voici une méthode qui fonctionne avec la nouvelle contrainte de type Enum
de C # 7.3. Notez que vous devez également spécifier qu'il s'agit également d'une struct
pour pouvoir en faire le nullable TEnum?
sinon vous obtiendrez une erreur.
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;
}
Pour analyser une valeur de chaîne en fonction des valeurs d'attribut appliquées aux membres enum, je vous recommande d'utiliser ma bibliothèque Enums.NET open source.
Pour un attribut personnalisé tel que StringValueAttribute
, vous le feriez.
Enregistrez et stockez une EnumFormat
personnalisée pour StringValueAttribute.Value
.
Format = Enums.RegisterCustomEnumFormat(m => m.Attributes.Get<StringValueAttribute>()?.Value);
Ensuite, utilisez la personnalisation EnumFormat
.
Als result = Enums.Parse<Als>("Niet beantwoord", Format); // result == Als.NietBeantwoord
Si vous utilisiez plutôt un attribut intégré tel que DescriptionAttribute
, vous pouvez simplement le faire.
Als result = Enums.Parse<Als>("Niet beantwoord", EnumFormat.Description);
Si cela vous intéresse, voici comment vous obtenez la valeur de chaîne associée à une valeur enum.
string value = Als.NietBeantwoord.AsString(Format); // value == "Niet beantwoord"