2012-03-07 18 views
24

Estoy construyendo una aplicación que hace un uso intensivo de Enum s para datos personalizados. Esencialmente, un objeto se almacena en la base de datos con aproximadamente 28 atributos separados. Cada atributo es un campo de dos caracteres que se traduce del SQL directamente a Enum.¿Son los atributos personalizados para los Enum peligrosos?

Desafortunadamente, también necesito traducir estos valores en dos valores diferentes legibles por humanos. Uno para una leyenda en una tabla de datos, y otro para una clase de CSS para darle estilo a una imagen en el front-end de la aplicación web.

Para hacer esto, he configurado dos atributos personalizados y los he aplicado al Enum cuando es necesario. Por ejemplo: Atributo

Interface atributo personalizado

public interface IAttribute<T> 
{ 
    T Value { get; } 
} 

Ejemplo Custom

public sealed class AbbreviationAttribute: Attribute, IAttribute<string> 
{ 
    private readonly string value; 

    public AbbreviationAttribute(string value) 
    { 
     this.value = value; 
    } 

    public string Value 
    { 
     get { return this.value; } 
    } 
} 

método para recuperar atributo personalizado de Enum

public static R GetAttributeValue<T, R>(IConvertible @enum) 
{ 
    R attributeValue = default(R); 

    if (@enum != null) 
    { 
     FieldInfo fi = @enum.GetType().GetField(@enum.ToString()); 

     if (fi != null) 
     { 
      T[] attributes = fi.GetCustomAttributes(typeof(T), false) as T[]; 

      if (attributes != null && attributes.Length > 0) 
      { 
       IAttribute<R> attribute = attributes[0] as IAttribute<R>; 

       if (attribute != null) 
       { 
        attributeValue = attribute.Value; 
       } 
      } 
     } 
    } 

    return attributeValue; 
} 

Ejemplo Enum el uso de este modelo de

public enum Download 
{ 
    [Abbreviation("check")] 
    [Description("Certified")] 
    C = 1, 

    [Abbreviation("no-formal")] 
    [Description("No formal certification")] 
    NF = 2, 

    [Abbreviation("cert-prob")] 
    [Description("Certified with potential problems")] 
    CP = 3 
} 

Tanto Abbreviation y Description son atributos personalizados que implementan IAttribute<T>. Mi actual Enum tiene 11 valores posibles, y como mencioné antes, se usa en 28 propiedades separadas en mi objeto personalizado. El uso de atributos personalizados parecía ser la mejor forma de mapear esta información de ida y vuelta.

Ahora, para la pregunta, ¿es esta la mejor manera de lograr esto? Guardo el valor Enum ("C", "NF" o "CP" en el fragmento de arriba) en la base de datos, pero necesito los valores de la abreviatura y descripción en mi código. Además, dudo que este sea el conjunto final de atributos personalizados que necesitaré.

Antes de seguir avanzando con este patrón ... ¿es la manera correcta de hacer las cosas? Prefiero solucionar problemas potenciales con este enfoque ahora que tener que rastrear y refactorizar más tarde.

+2

Pude ver algunos problemas de localización tal como está – asawyer

+0

Buen punto. Sin embargo, probablemente podría modificar 'IAttribute' para soportar una configuración de localización de estilo' gettext'. Estoy más preocupado por la escalabilidad, el rendimiento y las mejores prácticas de las que podría no estar al tanto. – EAMann

+0

'GetAttributeValue' no es un método de extensión contrario al texto de descripción anterior. –

Respuesta

13

Este es el mismo método que yo uso. El único inconveniente es la serialización. Los valores de los atributos personalizados no se serializan.

me gusta el método de atributo personalizado sobre el método de base de datos porque vincula los datos de atributo derecho a la enumeración en lugar de tener que utilizar una tabla de consulta o de clase, etc.

+1

El otro inconveniente es que tiene que volver a implementar completamente la aplicación si alguna vez una descripción cambia por un carácter – eouw0o83hf

+1

@ eouw0o83hf: verdadero. mitigado por las opciones de implementación recientes (también conocido como ClickOnce), pero estás en lo cierto. La mayoría de mis aplicaciones tienden a ser web o cosas con largos períodos entre ciclos de implementación donde muchas otras cosas van a cambiar, por lo que actualizar las descripciones de un par no es gran cosa. –

1

¿Se puede modificar la base de datos? Creo que la mejor opción sería crear una tabla (o tablas) para alojar los valores posibles de las enumeraciones y la clave externa de los objetos principales (en lugar de usar códigos de caracteres, esto hace que sea más fácil y normaliza tu BD) . Proporcione a la tabla una columna Abbreviation y Description, a continuación, extraiga los datos y haga referencia a ellos con su clave, y almacénelos en caché si las búsquedas son lentas.

Una cosa que es peligrosa acerca de los atributos es que si alguna de esas cadenas alguna vez tiene que cambiar, se trata de una redistribución completa de la aplicación. Si los convierte en valores de base de datos, puede cambiarlos con un simple UPDATE.

2

probablemente me construyo una tabla hash y un tipo especial para algo como esto. Es posible que ya hayas descartado la idea por alguna razón u otra, pero esto es lo que yo haría sin conocer los detalles de tu aplicación.

class SpecialType { 
    // include the fields and all attributes that you need to reference, ToString method for debugging, and any serialization you need 
    public string foo { get; set; } 
    public string bar { get; set; } 
    public ToString() { return "SpecialType with foo '" + foo + "' and bar '" + bar + "'"; } 
} 

Dictionary<int, SpecialType> myDict = new Dictionary<int, SpecialType> { 
    { 1, new SpecialType { foo = "XA1B2", bar = "XC3D4" } }, 
    { 2, new SpecialType { foo = "ZA1B2", bar = "ZC3D4" } }, 
    { 3, new SpecialType { foo = "YA1B2", bar = "YC3D4" } }, 
} 

Entonces podría fácilmente mantener enteros en mis otras clases para ahorrar memoria, averiguar si un valor particular era válido mediante la comprobación de la existencia en las llaves del diccionario, todas esas cosas. Probablemente sea mucho más fácil hacer enlaces de datos si finalmente va a usar WPF o leer/escribir en el disco, también.

Cuestiones relacionadas