Sé que lo siguiente no es posible porque el tipo de enumeración tiene que ser un int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
De mi base de datos obtengo un campo con códigos incomprensivos (los OEM
y CMB
s). Me gustaría convertir este campo en enum
algo o algo más comprensible. Porque si el objetivo es la legibilidad, la solución debe ser breve.
¿Qué otras opciones tengo?
Respuestas:
Me gusta usar propiedades en una clase en lugar de métodos, ya que se parecen más a una enumeración.
Aquí hay un ejemplo para un registrador:
Pase valores de cadena de tipo seguro como parámetro:
Uso:
fuente
ToString
método para regresarValue
. Y luego proporcionó operadores de conversión implícitos hacia y desde una cadena.public static implicit operator String(LogCategory category) { return Value; }
.También podría usar el modelo de extensión:
Su clase de extensión
uso:
fuente
public static string ToDescriptionString(this Enum ...
ie sin escribir explícitamente enMyEnum
.¿Qué tal usar una clase estática con constantes?
fuente
GroupTypes
como un tipo de argumento porque es una clase estática. Ese es el problema que la respuesta de Even Mien resuelve. En este caso, tendría que tenerlovoid DoSomething(string groupType)
, lo que significa quegroupType
podría tener cualquier valor de cadena , incluso valores que no esperaba, lo que significa que debe estar preparado para esos tipos no válidos y decidir cómo manejarlos (p. Ej. lanzando una excepción). Incluso la respuesta de Mien resuelve eso limitando el número de entradas válidas a las opciones definidas por laLogCategory
clase.Puede agregar atributos a los elementos en la enumeración y luego usar la reflexión para obtener los valores de los atributos.
Tendría que usar el especificador de "campo" para aplicar los atributos, así:
Luego reflexionaría sobre los campos estáticos del tipo de la enumeración (en este caso GroupTypes) y obtendría
DescriptionAttribute
el valor que estaba buscando utilizando la reflexión:Opté por devolver el
DescriptionAttribute
mismo arriba, en caso de que desee poder determinar si el atributo se aplica o no.fuente
Puedes hacerlo muy fácilmente en realidad. Usa el siguiente código.
Luego, cuando desee obtener el valor de cadena de cada elemento de enumeración, simplemente use la siguiente línea de código.
He usado este método con éxito en el pasado, y también he usado una clase de constantes para mantener constantes de cadena, ambas funcionan bastante bien, pero tiendo a preferir esto.
fuente
Intente agregar constantes a una clase estática. No terminas con un tipo, pero tendrás constantes legibles y organizadas:
fuente
Cree una segunda enumeración, para su base de datos que contenga lo siguiente:
Ahora, puede usar Enum.Parse para recuperar el valor correcto de DBGroupTypes de las cadenas "OEM" y "CMB". Luego puede convertirlos a int y recuperar los valores correctos de la enumeración correcta que desea utilizar más en su modelo.
fuente
Usa una clase.
Editar: mejor ejemplo
fuente
Otra forma de lidiar con el problema es tener una enumeración y una serie de cadenas que mapearán los valores de enumeración con la lista de cadenas:
puedes usarlo de esta manera:
Solicitará CMB
PROS:
CONTRAS:
fuente
Aquí está el método de extensión que utilicé para obtener el valor de enumeración como cadena. Primero aquí está la enumeración.
El atributo Descripción proviene de System.ComponentModel.
Y aquí está mi método de extensión:
Ahora, puede acceder a la enumeración como valor de cadena utilizando el siguiente código:
fuente
¿Has considerado una tabla de búsqueda con un diccionario?
Luego puede usar GroupTypeLookup. TryGetValue () para buscar una cadena cuando la lea.
fuente
fuente
C # no admite cadenas enumeradas, pero para la mayoría de las situaciones puede usar una Lista o Diccionario para obtener el efecto deseado.
Por ejemplo, para imprimir resultados aprobados / reprobados:
fuente
Lo convertiría en una clase y evitaría una enumeración por completo. Y luego, con el uso de un typehandler, puede crear el objeto cuando lo toma de la base de datos.
ES DECIR:
fuente
Simplemente crearía un diccionario y usaría el código como clave.
Editar: para abordar el comentario sobre hacer una búsqueda inversa (encontrar la clave), esto no sería terriblemente eficiente. Si esto es necesario, escribiría una nueva clase para manejarlo.
fuente
Mi primera pregunta: ¿tiene acceso a la base de datos? Esto debería normalizarse en la base de datos, idealmente, de lo contrario, cualquier solución será propensa a errores. En mi experiencia, los campos de datos llenos de "OEM" y "CMB" tienden a terminar teniendo cosas como "oem" y otros 'datos basura' mezclados a lo largo del tiempo ... Si puede normalizarlos, podría usar la clave en la tabla que contiene los elementos como Enum, y ya está, con una estructura mucho más limpia.
Si eso no está disponible, haría su Enum, y haría una clase para analizar su cadena en la Enum por usted. Esto al menos le daría cierta flexibilidad en el manejo de entradas no estándar y mucha más flexibilidad para atrapar o manejar errores que hacer cualquiera de las soluciones alternativas usando Enum.Parse / Reflection / etc. Un diccionario funcionaría, pero podría romperse si alguna vez tiene problemas de casos, etc.
Recomiendo escribir una clase para que puedas hacer:
Esto conserva la mayor parte de su legibilidad sin tener que cambiar la base de datos.
fuente
Si entiendo correctamente, necesita una conversión de cadena a enumeración:
Si lo desea, puede hacerlo más elegante con genéricos para el tipo de enumeración.
fuente
En VS 2015, puede usar nameof
Uso:
fuente
Un pequeño ajuste al método Glennular Extension, para que pueda usar la extensión en otras cosas que no sean ENUM;
O usando linq
fuente
Siguiendo la respuesta de @Even Mien, he intentado ir un poco más allá y hacerlo genérico, parece que estoy casi allí, pero un caso aún resiste y probablemente pueda simplificar un poco mi código.
Lo publico aquí si alguien ve cómo podría mejorar y sobre todo hacer que funcione, ya que no puedo asignarlo desde una cadena
Hasta ahora tengo los siguientes resultados:
Donde sucede la magia:
Solo entonces tengo que declarar esto para mis enumeraciones:
fuente
Nuevo en .Net Core 3.0 / C # 8.0 (si su entorno de trabajo le permite actualizar su proyecto) es una declaración de cambio breve que parece algo enumista. Al final del día, es la misma declaración de cambio aburrida que hemos estado usando durante años.
La única diferencia real aquí es que la declaración de cambio tiene un nuevo traje.
Notarás que el código anterior que copié desde aquí , en realidad está usando una enumeración como parámetro.
No es exactamente lo que quieres (y confía en mí, he querido algo similar a lo que el OP está solicitando durante mucho tiempo), pero realmente siento que esto es algo así como una rama de olivo de MS. JMO
Espero que ayude a alguien!
fuente
Usé una estructura como se aludió en una respuesta anterior, pero eliminé cualquier complejidad. Para mí, esto fue como crear una enumeración de cadenas. Se usa de la misma manera que se usa una enumeración.
Ejemplo de uso:
fuente
Incluso implementé algunas enumeraciones según lo sugerido por @Even (vía
class X
ypublic static X
miembros), solo para descubrir más tarde que en estos días, a partir de .Net 4.5, existe elToString()
método correcto .Ahora estoy reimplementando todo de nuevo a las enumeraciones.
fuente
Esta es una forma de usarlo como un parámetro fuertemente tipado o como una cadena :
fuente
Puedes usar dos enumeraciones. Uno para la base de datos y el otro para facilitar la lectura.
Solo necesita asegurarse de que permanezcan sincronizados, lo que parece un pequeño costo. No es necesario establecer los valores, solo establecer las posiciones de la misma manera, pero establecer los valores deja muy claro que las dos enumeraciones están relacionadas y evita que los errores reorganicen los miembros de la enumeración. Y un comentario le permite al equipo de mantenimiento saber que están relacionados y deben mantenerse sincronizados.
Para usarlo, primero debe convertir al código:
Luego, si desea hacerlo aún más conveniente, puede agregar una función de extensión que solo funcione para este tipo de enumeración:
y luego puedes hacer:
fuente
enum
un cambio de valor previsto en uno podría estropear involuntariamente al otro.Básicamente estaba buscando la respuesta Reflexión de @ArthurC
Solo para extender un poco su respuesta, puede hacerlo aún mejor si tiene una función genérica:
Entonces puedes envolver lo que tengas
o
fuente
Tomado de @EvenMien y agregado en algunos de los comentarios. (También para mi propio caso de uso)
fuente
Agregar esta clase
Este trabajo está usando
CallerMemberName
para minimizar la codificación.Utilizando:
Pruébalo:
salida:
fuente
Basado en otras opiniones, esto es lo que se me ocurre. Este enfoque evita tener que escribir .Value donde desea obtener el valor constante.
Tengo una clase base para todas las enumeraciones de cadenas como esta:
El JsonConverter es así:
Y una enumeración de cadena real será algo como esto:
Y con esto, puede usar Color.Red para incluso serializar a json sin usar la propiedad Value
fuente
No necesitaba nada robusto como almacenar la cadena en atributos. Solo necesitaba convertir algo así
MyEnum.BillEveryWeek
en "factura todas las semanas" oMyEnum.UseLegacySystem
en "usar un sistema heredado", básicamente dividir la enumeración por su carcasa de camello en palabras individuales en minúsculas.MyEnum.UseLegacySystem.UnCamelCase()
salidas "usar sistema heredado"Si tiene varios indicadores configurados, lo convertirá en inglés simple (delimitado por comas excepto una "y" en lugar de la última coma).
fuente