C# 获取枚举值的属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1799370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting attributes of Enum's value
提问by Alex K
I would like to know if it is possible to get attributes of the enum
values and not of the enum
itself? For example, suppose I have the following enum
:
我想知道是否有可能获得enum
值的属性而不是enum
它本身的属性?例如,假设我有以下内容enum
:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
What I want is given the enum type, produce 2-tuples of enum string value and its description.
我想要的是枚举类型,生成枚举字符串值的 2 元组及其描述。
Value was easy:
价值很简单:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
But how do I get description attribute's value, to populate Tuple.Desc
? I can think of how to do it if the Attribute belongs to the enum
itself, but I am at a loss as to how to get it from the value of the enum
.
但是如何获取 description 属性的值来填充Tuple.Desc
?如果 Attribute 属于enum
它自己,我可以想到如何去做,但我不知道如何从enum
.
采纳答案by Bryan Rowe
This should do what you need.
这应该做你需要的。
var enumType = typeof(FunkyAttributesEnum);
var memberInfos = enumType.GetMember(FunkyAttributesEnum.NameWithoutSpaces1.ToString());
var enumValueMemberInfo = memberInfos.FirstOrDefault(m => m.DeclaringType == enumType);
var valueAttributes =
enumValueMemberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
var description = ((DescriptionAttribute)valueAttributes[0]).Description;
回答by Ian P
Alternatively, you could do the following:
或者,您可以执行以下操作:
Dictionary<FunkyAttributesEnum, string> description = new Dictionary<FunkyAttributesEnum, string>()
{
{ FunkyAttributesEnum.NameWithoutSpaces1, "Name With Spaces1" },
{ FunkyAttributesEnum.NameWithoutSpaces2, "Name With Spaces2" },
};
And get the description with the following:
并使用以下内容获取描述:
string s = description[FunkyAttributesEnum.NameWithoutSpaces1];
In my opinion this is a more efficient way of doing what you want to accomplish, as no reflection is needed..
在我看来,这是一种更有效的方式来完成您想要完成的工作,因为不需要反思。
回答by Scott Belchak
This is a generic implementation using a lambda for the selection
这是使用 lambda 进行选择的通用实现
public static Expected GetAttributeValue<T, Expected>(this Enum enumeration, Func<T, Expected> expression)
where T : Attribute
{
T attribute =
enumeration
.GetType()
.GetMember(enumeration.ToString())
.Where(member => member.MemberType == MemberTypes.Field)
.FirstOrDefault()
.GetCustomAttributes(typeof(T), false)
.Cast<T>()
.SingleOrDefault();
if (attribute == null)
return default(Expected);
return expression(attribute);
}
Call it like this:
像这样调用它:
string description = targetLevel.GetAttributeValue<DescriptionAttribute, string>(x => x.Description);
回答by AdamCrawford
This piece of code should give you a nice little extension method on any enum that lets you retrieve a generic attribute. I believe it's different to the lambda function above because it's simpler to use and slightly - you only need to pass in the generic type.
这段代码应该在任何枚举上为您提供一个不错的小扩展方法,让您检索通用属性。我相信它与上面的 lambda 函数不同,因为它使用起来更简单,而且稍微——你只需要传入泛型类型。
public static class EnumHelper
{
/// <summary>
/// Gets an attribute on an enum field value
/// </summary>
/// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
/// <param name="enumVal">The enum value</param>
/// <returns>The attribute of type T that exists on the enum value</returns>
/// <example><![CDATA[string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;]]></example>
public static T GetAttributeOfType<T>(this Enum enumVal) where T:System.Attribute
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
return (attributes.Length > 0) ? (T)attributes[0] : null;
}
}
回答by Coda
You can also define an enum value like Name_Without_Spaces
, and when you want a description use Name_Without_Spaces.ToString().Replace('_', ' ')
to replace the underscores with spaces.
您还可以定义一个枚举值,如Name_Without_Spaces
,并且当您想要描述时使用Name_Without_Spaces.ToString().Replace('_', ' ')
空格替换下划线。
回答by Nick N.
I implemented this extension method to get the description from enum values. It works for all kind of enums.
我实现了这个扩展方法来从枚举值中获取描述。它适用于所有类型的枚举。
public static class EnumExtension
{
public static string ToDescription(this System.Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : value.ToString();
}
}
回答by FunksMaName
In addition to AdamCrawford response, I've further created a more specialized extension methods that feed of it to get the description.
除了AdamCrawford response 之外,我还进一步创建了一个更专业的扩展方法来获取描述。
public static string GetAttributeDescription(this Enum enumValue)
{
var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>();
return attribute == null ? String.Empty : attribute.Description;
}
hence, to get the description, you could either use the original extension method as
因此,要获得描述,您可以使用原始扩展方法作为
string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description
or you could simply call the the extension method here as:
或者你可以简单地调用这里的扩展方法:
string desc = myEnumVariable.GetAttributeDescription();
Which should hopefully make your code a bit more readable.
这应该有望使您的代码更具可读性。
回答by Colin
Here is code to get information from a Display attribute. It uses a generic method to retrieve the attribute. If the attribute is not found it converts the enum value to a string with pascal/camel case converted to title case (code obtained here)
下面是从 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();
}
}
And this is the extension method for strings for converting to 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]))", " "));
}
回答by saille
This extension method will obtain a string representation of an enum value using its XmlEnumAttribute. If no XmlEnumAttribute is present, it falls back to enum.ToString().
此扩展方法将使用其 XmlEnumAttribute 获取枚举值的字符串表示形式。如果不存在 XmlEnumAttribute,则回退到 enum.ToString()。
public static string ToStringUsingXmlEnumAttribute<T>(this T enumValue)
where T: struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
string name;
var type = typeof(T);
var memInfo = type.GetMember(enumValue.ToString());
if (memInfo.Length == 1)
{
var attributes = memInfo[0].GetCustomAttributes(typeof(System.Xml.Serialization.XmlEnumAttribute), false);
if (attributes.Length == 1)
{
name = ((System.Xml.Serialization.XmlEnumAttribute)attributes[0]).Name;
}
else
{
name = enumValue.ToString();
}
}
else
{
name = enumValue.ToString();
}
return name;
}
回答by Troy Alford
I've merged a couple of the answers here to create a little more extensible solution. I'm providing it just in case it's helpful to anyone else in the future. Original posting here.
我在这里合并了几个答案以创建一个更具扩展性的解决方案。我提供它以防万一它在未来对其他人有帮助。原帖在这里。
using System;
using System.ComponentModel;
public static class EnumExtensions {
// This extension method is broken out so you can use a similar pattern with
// other MetaData elements in the future. This is your base method for each.
public static T GetAttribute<T>(this Enum value) where T : Attribute {
var type = value.GetType();
var memberInfo = type.GetMember(value.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
return attributes.Length > 0
? (T)attributes[0]
: null;
}
// This method creates a specific call to the above method, requesting the
// Description MetaData attribute.
public static string ToName(this Enum value) {
var attribute = value.GetAttribute<DescriptionAttribute>();
return attribute == null ? value.ToString() : attribute.Description;
}
}
This solution creates a pair of extension methods on Enum. The first allows you to use reflection to retrieve any attribute associated with your value. The second specifically calls retrieves the DescriptionAttribute
and returns it's Description
value.
此解决方案在 Enum 上创建了一对扩展方法。第一个允许您使用反射来检索与您的值相关联的任何属性。第二个专门调用检索DescriptionAttribute
并返回它的Description
值。
As an example, consider using the DescriptionAttribute
attribute from System.ComponentModel
例如,考虑使用DescriptionAttribute
来自的属性System.ComponentModel
using System.ComponentModel;
public enum Days {
[Description("Sunday")]
Sun,
[Description("Monday")]
Mon,
[Description("Tuesday")]
Tue,
[Description("Wednesday")]
Wed,
[Description("Thursday")]
Thu,
[Description("Friday")]
Fri,
[Description("Saturday")]
Sat
}
To use the above extension method, you would now simply call the following:
要使用上述扩展方法,您现在只需调用以下代码:
Console.WriteLine(Days.Mon.ToName());
or
或者
var day = Days.Mon;
Console.WriteLine(day.ToName());