私が持っている
public enum Als
{
[StringValue("Beantwoord")] Beantwoord = 0,
[StringValue("Niet beantwoord")] NietBeantwoord = 1,
[StringValue("Geselecteerd")] Geselecteerd = 2,
[StringValue("Niet geselecteerd")] NietGeselecteerd = 3,
}
と
public class StringValueAttribute : Attribute
{
private string _value;
public StringValueAttribute(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
そして、コンボボックスで選択したアイテムの値をintに入れたいと思います。
int i = (int)(Als)Enum.Parse(typeof(Als), (string)cboAls.SelectedValue); //<- WRONG
これは可能ですか?もしそうなら、どのように? (StringValue
はコンボボックスから選択された値と一致します)。
これがあなたを正しい方向に向けるべきヘルパーメソッドです。
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.");
}
そしてそれを呼び出すには、次のようにします。
Als result = this.GetEnumByStringValueAttribute<Als>(ComboBox.SelectedValue);
これはAls
に関連付けられているため、おそらく最善の解決策ではなく、このコードを再利用可能にする必要があります。私のソリューションからコードを取り除いて属性値を返し、質問で行っているようにEnum.Parse
を使用することをお勧めします。
Microsoftの DescriptionAttribute と次の拡張メソッドを使用しています。
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;
}
これが私がこの正確な目的のために使用するいくつかの拡張メソッドです。あなたのStringValueAttribute
を使用するようにこれらを書き直しましたが、 Oliver のように DescriptionAttribute を使用します私のコードで。
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);
}
これは、.NET4.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);
}
そしてそれを呼び出すには、次のようにします。
Als result = ComboBox.SelectedValue.FromEnumStringValue<Als>();
逆に、列挙値から文字列を取得する関数は次のとおりです。
public static string StringValue(this Enum enumItem) {
return enumItem
.GetType()
.GetField(enumItem.ToString())
.GetCustomAttributes<StringValueAttribute>()
.Select(a => a.Value)
.FirstOrDefault() ?? enumItem.ToString();
}
そしてそれを呼ぶために:
string description = Als.NietBeantwoord.StringValue()
私がここで何かを逃しているかどうかわからない、あなたはこれをすることができない、
Als temp = (Als)combo1.SelectedItem;
int t = (int)temp;
この非常に賛成の質問と回答 の重複リンクからここに来て、これはC#7.3の新しいEnum
型制約で機能するメソッドです。 null許容型のTEnum?
にすることができるように、それもstruct
であることも指定する必要があることに注意してください。そうしないと、エラーが発生します。
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;
}
もっとgenericソリューションを作りました。
any属性で使用でき、文字列以外のタイプでも使用できます。
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
}
}
@RubenHermanの最初の投稿:
Als Beantwoord = EnumExtensions.FromAttributeValueToEnum<Als>(typeof(StringValueAttribute), nameof(StringValueAttribute.Value), "Beantwoord");
高度なサンプル:
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);
列挙型メンバーに適用された属性値に基づいて文字列値を解析するには、私の Enums.NET オープンソースライブラリを使用することをお勧めします。
StringValueAttribute
のようなカスタム属性の場合、これを行います。
StringValueAttribute.Value
のカスタムEnumFormat
を登録して保存します。
Format = Enums.RegisterCustomEnumFormat(m => m.Attributes.Get<StringValueAttribute>()?.Value);
次に、カスタムEnumFormat
を使用します。
Als result = Enums.Parse<Als>("Niet beantwoord", Format); // result == Als.NietBeantwoord
代わりに、 DescriptionAttribute
などの組み込み属性を使用している場合は、これを行うことができます。
Als result = Enums.Parse<Als>("Niet beantwoord", EnumFormat.Description);
興味がある場合は、これが列挙値に関連付けられた文字列値を取得する方法です。
string value = Als.NietBeantwoord.AsString(Format); // value == "Niet beantwoord"