我目前正在實現一個基於this suggestion字符串和枚舉associations。那是,我有一個Description
屬性與每個枚舉元素相關聯。在該頁面上還有一個函數,該函數根據給定的枚舉返回描述的字符串。我現在要實現的是反向函數,即給定一個輸入字符串查找帶有相應描述的枚舉(如果存在),否則返回null。字符串到枚舉與描述
我試過(T) Enum.Parse(typeof(T), "teststring")
但它會拋出異常。
我目前正在實現一個基於this suggestion字符串和枚舉associations。那是,我有一個Description
屬性與每個枚舉元素相關聯。在該頁面上還有一個函數,該函數根據給定的枚舉返回描述的字符串。我現在要實現的是反向函數,即給定一個輸入字符串查找帶有相應描述的枚舉(如果存在),否則返回null。字符串到枚舉與描述
我試過(T) Enum.Parse(typeof(T), "teststring")
但它會拋出異常。
你必須寫自己的逆向方法:
enum SomeEnum {
[Description("First Value")]
FirstValue,
SecondValue
}
SomeEnum value = ParseDescriptionToEnum<SomeEnum>("First Value");
即通過測試。股票Parse()方法顯然不知道你的描述屬性。
像這樣的東西應該工作:
public static T GetEnumValueFromDescription<T>(string description)
{
MemberInfo[] fis = typeof(T).GetFields();
foreach (var fi in fis)
{
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0 && attributes[0].Description == description)
return (T)Enum.Parse(typeof(T), fi.Name);
}
throw new Exception("Not found");
}
你要找到一個更好的東西不是拋出一個異常,如果沒有找到枚舉值做,雖然。 :)
偉大的解決方案!我沒有拋出異常,而是使用默認的枚舉分析。這涵蓋了您可能沒有關於枚舉中每個選項的description屬性的場景。 – norepro 2011-12-01 00:45:30
This answer到相關問題顯示如何檢索給定類型的屬性。您可以使用類似的方法將給定的字符串與Enum
的描述屬性進行比較。
static string GetEnumDescription<T>(T value) {
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false
);
if (attributes != null &&
attributes.Length > 0) {
return attributes[0].Description;
}
else {
return value.ToString();
}
}
static T ParseDescriptionToEnum<T>(string description) {
Array array = Enum.GetValues(typeof(T));
var list = new List<T>(array.Length);
for(int i = 0; i < array.Length; i++) {
list.Add((T)array.GetValue(i));
}
var dict = list.Select(v => new {
Value = v,
Description = GetEnumDescription(v) }
)
.ToDictionary(x => x.Description, x => x.Value);
return dict[description];
}
我沒有嘗試進行錯誤檢查。請注意,字典不需要在每次調用該方法時創建,但我懶得解決這個問題。
用法:
[Fact]
public void Can_parse_a_value_with_a_description_to_an_enum() {
string description = "First Value";
SomeEnum value = ParseDescriptionToEnum<SomeEnum>(description);
Assert.Equal(SomeEnum.FirstValue, value);
}
[Fact]
public void Can_parse_a_value_without_a_description_to_an_enum() {
string description = "SecondValue";
SomeEnum value = ParseDescriptionToEnum<SomeEnum>(description);
Assert.Equal(SomeEnum.SecondValue, value);
}
我會upvoted安娜的答案,但我沒有這樣做的聲譽。這部分基於她的答案,這是我提出的一種雙向解決方案。向ParseEnum方法提供defaultValue包括相同Enum根據其使用情況可能具有不同默認值的情況。
public static string GetDescription<T>(this object enumerationValue) where T : struct
{
// throw an exception if enumerationValue is not an Enum
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
DescriptionAttribute[] attributes = (DescriptionAttribute[])memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
//Pull out the description value
return attributes[0].Description;
}
}
//In case we have no description attribute, we'll just return the ToString of the enum
return enumerationValue.ToString();
}
public static T ParseEnum<T>(this string stringValue, T defaultValue)
{
// throw an exception if T is not an Enum
Type type = typeof(T);
if (!type.IsEnum)
{
throw new ArgumentException("T must be of Enum type", "T");
}
//Tries to find a DescriptionAttribute for a potential friendly name for the enum
MemberInfo[] fields = type.GetFields();
foreach (var field in fields)
{
DescriptionAttribute[] attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0 && attributes[0].Description == stringValue)
{
return (T)Enum.Parse(typeof(T), field.Name);
}
}
//In case we couldn't find a matching description attribute, we'll just return the defaultValue that we provided
return defaultValue;
}
您也可以使用Humanizer。爲了讓你寫的說明:
EAssemblyUnit.eUCAL1.Humanize();
,並得到枚舉從描述,這是你想要的時候,你可以這樣寫:
"UCAL1".DehumanizeTo<EAssemblyUnit>();
免責聲明:我Humanizer的創造者。
可能重複的[你可以訪問一個特定枚舉值的長描述。](http://stackoverflow.com/questions/1473870/can-you-access-a-long-description-for-a-specific - 價值) – NotMe 2010-11-22 20:04:42