我想知道是否有可能获得枚举值的属性,而不是枚举本身?例如,假设我有以下枚举:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
我想要的是给定枚举类型,产生枚举字符串值及其描述的二元组。
价值很简单:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
但我如何获得描述属性的值,以填充Tuple.Desc?如果属性属于枚举本身,我可以想到如何做到这一点,但我不知道如何从枚举的值中获得它。
朋友们,如果有帮助的话,我将与你们分享我的解决方案:
Custom属性的定义:
[AttributeUsage(AttributeTargets.Field,AllowMultiple = false)]
public class EnumDisplayName : Attribute
{
public string Name { get; private set; }
public EnumDisplayName(string name)
{
Name = name;
}
}
现在因为我需要它在HtmlHelper扩展的HtmlHelper定义内:
public static class EnumHelper
{
public static string EnumDisplayName(this HtmlHelper helper,EPriceType priceType)
{
//Get every fields from enum
var fields = priceType.GetType().GetFields();
//Foreach field skipping 1`st fieldw which keeps currently sellected value
for (int i = 0; i < fields.Length;i++ )
{
//find field with same int value
if ((int)fields[i].GetValue(priceType) == (int)priceType)
{
//get attributes of found field
var attributes = fields[i].GetCustomAttributes(false);
if (attributes.Length > 0)
{
//return name of found attribute
var retAttr = (EnumDisplayName)attributes[0];
return retAttr.Name;
}
}
}
//throw Error if not found
throw new Exception("Błąd podczas ustalania atrybutów dla typu ceny allegro");
}
}
希望能有所帮助
下面是从Display属性获取信息的代码。它使用泛型方法检索属性。如果没有找到该属性,它将枚举值转换为字符串,将pascal/camel大小写转换为标题大小写(此处获得的代码)
public static class EnumHelper
{
// Get the Name value of the Display attribute if the
// enum has one, otherwise use the value converted to title case.
public static string GetDisplayName<TEnum>(this TEnum value)
where TEnum : struct, IConvertible
{
var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
return attr == null ? value.ToString().ToSpacedTitleCase() : attr.Name;
}
// Get the ShortName value of the Display attribute if the
// enum has one, otherwise use the value converted to title case.
public static string GetDisplayShortName<TEnum>(this TEnum value)
where TEnum : struct, IConvertible
{
var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>();
return attr == null ? value.ToString().ToSpacedTitleCase() : attr.ShortName;
}
/// <summary>
/// Gets an attribute on an enum field value
/// </summary>
/// <typeparam name="TEnum">The enum type</typeparam>
/// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
/// <param name="value">The enum value</param>
/// <returns>The attribute of type T that exists on the enum value</returns>
private static T GetAttributeOfType<TEnum, T>(this TEnum value)
where TEnum : struct, IConvertible
where T : Attribute
{
return value.GetType()
.GetMember(value.ToString())
.First()
.GetCustomAttributes(false)
.OfType<T>()
.LastOrDefault();
}
}
这是字符串转换为title case的扩展方法:
/// <summary>
/// Converts camel case or pascal case to separate words with title case
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ToSpacedTitleCase(this string s)
{
//https://stackoverflow.com/a/155486/150342
CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
TextInfo textInfo = cultureInfo.TextInfo;
return textInfo
.ToTitleCase(Regex.Replace(s,
"([a-z](?=[A-Z0-9])|[A-Z](?=[A-Z][a-z]))", "$1 "));
}
除了AdamCrawford响应之外,我还进一步创建了一个更专门的扩展方法来获取它的描述。
public static string GetAttributeDescription(this Enum enumValue)
{
var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>();
return attribute == null ? String.Empty : attribute.Description;
}
因此,要获得描述,您可以使用原始扩展方法as
string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description
或者你可以简单地调用这里的扩展方法:
string desc = myEnumVariable.GetAttributeDescription();
这应该会使您的代码更具可读性。