Obtener atributos del valor de Enum
¿Me gustaría saber si es posible obtener atributos de los enum
valores y no del enum
mismo? Por ejemplo, supongamos que tengo lo siguiente enum
:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
Lo que quiero es dar el tipo de enumeración, producir 2 tuplas del valor de la cadena de enumeración y su descripción.
El valor fue fácil:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
Pero, ¿cómo consigo que se complete el valor del atributo de descripción Tuple.Desc
? Puedo pensar en cómo hacerlo si el Atributo pertenece a enum
sí mismo, pero no sé cómo obtenerlo del valor de enum
.
Esto debería hacer lo que necesitas.
try
{
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;
}
catch
{
return FunkyAttributesEnum.NameWithoutSpaces1.ToString()
}
Este fragmento de código debería brindarle un pequeño método de extensión agradable en cualquier enumeración que le permita recuperar un atributo genérico. Creo que es diferente a la función lambda anterior porque es más simple de usar y ligeramente: solo necesita pasar el tipo genérico.
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;
}
}
El uso entonces sería:
string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;
Esta es una implementación genérica que utiliza una lambda para la selección.
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);
}
Llámalo así:
string description = targetLevel.GetAttributeValue<DescriptionAttribute, string>(x => x.Description);
He fusionado un par de respuestas aquí para crear una solución un poco más extensible. Lo proporciono por si a alguien le resulta útil en el futuro. Publicación original aquí .
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;
}
}
Esta solución crea un par de métodos de extensión en Enum. El primero le permite utilizar la reflexión para recuperar cualquier atributo asociado con su valor. El segundo llama específicamente recupera DescriptionAttribute
y devuelve su Description
valor.
Como ejemplo, considere usar el DescriptionAttribute
atributo deSystem.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
}
Para utilizar el método de extensión anterior, ahora simplemente llamaría a lo siguiente:
Console.WriteLine(Days.Mon.ToName());
o
var day = Days.Mon;
Console.WriteLine(day.ToName());