que español enum c# reflection enums .net-attributes

español - enum c# string



Obtención de atributos de valor de Enum (19)

Me gustaría saber si es posible obtener atributos de los valores de enumeración y no de la enumeración en sí. Por ejemplo, supongamos que tengo la siguiente enumeración:

using System.ComponentModel; // for DescriptionAttribute enum FunkyAttributesEnum { [Description("Name With Spaces1")] NameWithoutSpaces1, [Description("Name With Spaces2")] NameWithoutSpaces2 }

Lo que quiero es el tipo de enumeración, producir 2 tuplas de valor de 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 obtengo el valor del atributo de descripción para completar Tuple.Desc? Se me ocurre cómo hacerlo si el atributo pertenece a la enumeración en sí, pero no sé cómo obtenerlo del valor de la enumeración.


Añadiendo mi solución para Net Framework y NetCore.

Utilicé esto para mi implementación de Net Framework:

public static class EnumerationExtension { public static string Description( this Enum value ) { // get attributes var field = value.GetType().GetField( value.ToString() ); var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false ); // return description return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found"; } }

Esto no funciona para NetCore, así que lo modifiqué para hacer esto:

public static class EnumerationExtension { public static string Description( this Enum value ) { // get attributes var field = value.GetType().GetField( value.ToString() ); var attributes = field.GetCustomAttributes( false ); // Description is in a hidden Attribute class called DisplayAttribute // Not to be confused with DisplayNameAttribute dynamic displayAttribute = null; if (attributes.Any()) { displayAttribute = attributes.ElementAt( 0 ); } // return description return displayAttribute?.Description ?? "Description Not Found"; } }

Ejemplo de enumeración:

public enum ExportTypes { [Display( Name = "csv", Description = "text/csv" )] CSV = 0 }

Uso de la muestra para cualquier estática agregada:

var myDescription = myEnum.Description();


Además de la respuesta de AdamCrawford , también he creado una extensión más especializada que se alimenta para obtener la descripción.

public static string GetAttributeDescription(this Enum enumValue) { var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>(); return attribute == null ? String.Empty : attribute.Description; }

por lo tanto, para obtener la descripción, puede utilizar el método de extensión original como

string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description

o simplemente puede llamar al método de extensión aquí como:

string desc = myEnumVariable.GetAttributeDescription();

Lo que esperamos debería hacer su código un poco más legible.


Alternativamente, podrías hacer lo siguiente:

Dictionary<FunkyAttributesEnum, string> description = new Dictionary<FunkyAttributesEnum, string>() { { FunkyAttributesEnum.NameWithoutSpaces1, "Name With Spaces1" }, { FunkyAttributesEnum.NameWithoutSpaces2, "Name With Spaces2" }, };

Y obtenga la descripción con lo siguiente:

string s = description[FunkyAttributesEnum.NameWithoutSpaces1];

En mi opinión, esta es una forma más eficiente de hacer lo que quiere lograr, ya que no se necesita reflexión.


Aprovechando algunas de las funciones más nuevas del lenguaje C #, puede reducir el recuento de líneas:

public static TAttribute GetEnumAttribute<TAttribute>(this Enum enumVal) where TAttribute : Attribute { var memberInfo = enumVal.GetType().GetMember(enumVal.ToString()); return memberInfo[0].GetCustomAttributes(typeof(TAttribute), false).OfType<TAttribute>().FirstOrDefault(); } public static string GetEnumDescription(this Enum enumValue) => enumValue.GetEnumAttribute<DescriptionAttribute>()?.Description ?? enumValue.ToString();


Aquí está el código para obtener información de un atributo de visualización. Utiliza un método genérico para recuperar el atributo. Si no se encuentra el atributo, convierte el valor de enumeración en una cadena con el caso de pascal / camel convertido en caso de título (código obtenido here )

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(); } }

Y este es el método de extensión para cadenas para convertir a título de caso:

/// <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://.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 ")); }


Aquí está la versión .NET Core de la respuesta de AdamCrawford, utilizando System.Reflection.TypeExtensions ;

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>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()); IEnumerable<Attribute> attributes = memInfo[0].GetCustomAttributes(typeof(T), false); return (T)attributes?.ToArray()[0]; } }


Chicos, si les ayuda, compartiré con ustedes mi solución: Definición de atributo personalizado:

[AttributeUsage(AttributeTargets.Field,AllowMultiple = false)] public class EnumDisplayName : Attribute { public string Name { get; private set; } public EnumDisplayName(string name) { Name = name; } }

Ahora porque lo necesitaba dentro de la definición HtmlHelper de la Extensión 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"); } }

Espero eso ayude


Esta es una implementación genérica utilizando un 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);


Esta respuesta para configurar un cuadro combinado a partir de una enumeración de atributos que fue genial.

Luego tuve que codificar lo contrario para poder obtener la selección del cuadro y devolver la enumeración en el tipo correcto.

También modifiqué el código para manejar el caso donde faltaba un atributo

Para los beneficios de la siguiente persona, aquí está mi solución final.

public static class Program { static void Main(string[] args) { // display the description attribute from the enum foreach (Colour type in (Colour[])Enum.GetValues(typeof(Colour))) { Console.WriteLine(EnumExtensions.ToName(type)); } // Get the array from the description string xStr = "Yellow"; Colour thisColour = EnumExtensions.FromName<Colour>(xStr); Console.ReadLine(); } public enum Colour { [Description("Colour Red")] Red = 0, [Description("Colour Green")] Green = 1, [Description("Colour Blue")] Blue = 2, Yellow = 3 } } 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); // check if no attributes have been specified. if (((Array)attributes).Length > 0) { return (T)attributes[0]; } else { return 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; } /// <summary> /// Find the enum from the description attribute. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="desc"></param> /// <returns></returns> public static T FromName<T>(this string desc) where T : struct { string attr; Boolean found = false; T result = (T)Enum.GetValues(typeof(T)).GetValue(0); foreach (object enumVal in Enum.GetValues(typeof(T))) { attr = ((Enum)enumVal).ToName(); if (attr == desc) { result = (T)enumVal; found = true; break; } } if (!found) { throw new Exception(); } return result; } }

}


Este fragmento de código debería darle un pequeño método de extensión 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 fácil de usar y un poco más: 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>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; } }


Este método de extensión obtendrá una representación de cadena de un valor enum utilizando su XmlEnumAttribute. Si no hay ningún XmlEnumAttribute, vuelve a 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; }


Esto debería hacer lo que necesitas.

var type = typeof(FunkyAttributesEnum); var memInfo = type.GetMember(FunkyAttributesEnum.NameWithoutSpaces1.ToString()); var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); var description = ((DescriptionAttribute)attributes[0]).Description;


He fusionado un par de respuestas aquí para crear una solución un poco más extensible. Lo estoy proporcionando por si acaso es útil para alguien más en el futuro. Publicación original 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; } }

Esta solución crea un par de métodos de extensión en Enum. El primero le permite usar la reflexión para recuperar cualquier atributo asociado con su valor. La segunda llamada específicamente recupera el atributo de DescriptionAttribute y devuelve su valor de Description .

Como ejemplo, considere usar el atributo DescriptionAttribute de 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 }

Para usar el método de extensión anterior, ahora simplemente llamaría lo siguiente:

Console.WriteLine(Days.Mon.ToName());

o

var day = Days.Mon; Console.WriteLine(day.ToName());


Implementé este método de extensión para obtener la descripción de los valores enum. Funciona para todo tipo de enumeraciones.

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(); } }


Obtener el diccionario de enumeración.

public static IDictionary<string, int> ToDictionary(this Type enumType) { return Enum.GetValues(enumType) .Cast<object>() .ToDictionary(v => ((Enum)v).ToEnumDescription(), k => (int)k); }

Ahora llama a esto como ...

var dic = typeof(ActivityType).ToDictionary();

Método EnumDecription Ext

public static string ToEnumDescription(this Enum en) //ext method { Type type = en.GetType(); MemberInfo[] memInfo = type.GetMember(en.ToString()); if (memInfo != null && memInfo.Length > 0) { object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (attrs != null && attrs.Length > 0) return ((DescriptionAttribute)attrs[0]).Description; } return en.ToString(); } public enum ActivityType { [Description("Drip Plan Email")] DripPlanEmail = 1, [Description("Modification")] Modification = 2, [Description("View")] View = 3, [Description("E-Alert Sent")] EAlertSent = 4, [Description("E-Alert View")] EAlertView = 5 }


También puede definir un valor de enumeración como Name_Without_Spaces , y cuando desee una descripción, use Name_Without_Spaces.ToString().Replace(''_'', '' '') para reemplazar los guiones bajos con espacios.


Y si quieres la lista completa de nombres puedes hacer algo como

typeof (PharmacyConfigurationKeys).GetFields() .Where(x => x.GetCustomAttributes(false).Any(y => typeof(DescriptionAttribute) == y.GetType())) .Select(x => ((DescriptionAttribute)x.GetCustomAttributes(false)[0]).Description);


Fluido un trazador de líneas ...

Aquí estoy usando DisplayAttribute que contiene las propiedades de Name y Description .

public static DisplayAttribute GetDisplayAttributesFrom(this Enum enumValue, Type enumType) { return enumType.GetMember(enumValue.ToString()) .First() .GetCustomAttribute<DisplayAttribute>(); }

Ejemplo

public enum ModesOfTransport { [Display(Name = "Driving", Description = "Driving a car")] Land, [Display(Name = "Flying", Description = "Flying on a plane")] Air, [Display(Name = "Sea cruise", Description = "Cruising on a dinghy")] Sea } void Main() { ModesOfTransport TransportMode = ModesOfTransport.Sea; DisplayAttribute metadata = TransportMode.GetDisplayAttributesFrom(typeof(ModesOfTransport)); Console.WriteLine("Name: {0} /nDescription: {1}", metadata.Name, metadata.Description); }

Salida

Name: Sea cruise Description: Cruising on a dinghy


public enum DataFilters { [Display(Name= "Equals")] Equals = 1,// Display Name and Enum Name are same [Display(Name= "Does Not Equal")] DoesNotEqual = 2, // Display Name and Enum Name are different }

Ahora producirá error en este caso 1 "Igual a"

public static string GetDisplayName(this Enum enumValue) { var enumMember = enumValue.GetType().GetMember(enumValue.ToString()).First(); return enumMember.GetCustomAttribute<DisplayAttribute>() != null ? enumMember.GetCustomAttribute<DisplayAttribute>().Name : enumMember.Name; }

por lo tanto, si es el mismo nombre de enumeración de retorno en lugar del nombre de visualización porque enumMember.GetCustomAttribute () se anula si el nombre de visualización y el nombre de enumeración son los mismos ...