2012-03-07 48 views
24

Sto costruendo un'applicazione che fa un uso pesante di Enum s per dati personalizzati. Essenzialmente, un oggetto è memorizzato nel database con circa 28 attributi separati. Ogni attributo è un campo di due caratteri che viene tradotto dall'SQL direttamente su Enum.Gli attributi personalizzati per Enum sono pericolosi?

Purtroppo, ho anche bisogno di tradurre questi valori in due valori diversi leggibili dall'uomo. Uno per una legenda su una tabella di dati e uno per una classe CSS per lo stile di un'immagine sul front-end dell'applicazione Web.

Per fare ciò, ho impostato due attributi personalizzati e li ho applicati allo Enum se necessario. Ad esempio:

Abilità personalizzata interfaccia

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

Esempio attributo personalizzato

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

metodo per recuperare attributi personalizzati da 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; 
} 

Esempio Enum Uso Questo modello

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 
} 

Sia Abbreviation e Description sono attributi personalizzati che implementano IAttribute<T>. Il mio attuale Enum ha 11 valori possibili, e come ho detto prima è usato in 28 proprietà separate nel mio oggetto personalizzato. L'utilizzo di attributi personalizzati è sembrato il modo migliore per mappare queste informazioni avanti e indietro.

Ora per la domanda, è questo il modo migliore per realizzare questo? Memorizzo il valore Enum ("C", "NF" o "CP" nello snippet in alto) nel database, ma ho bisogno dei valori dell'abbreviazione e della descrizione nel mio codice. Inoltre, dubito che questo sarà il set finale di attributi personalizzati di cui ho bisogno.

Prima di continuare ad andare avanti con questo schema ... è il modo giusto di fare le cose? Mi piacerebbe piuttosto risolvere potenziali problemi con questo approccio ora di dover rintracciare e refactoring in seguito.

+2

Potrei vedere alcuni problemi di localizzazione così com'è – asawyer

+0

Buon punto. Potrei probabilmente modificare 'IAttribute' per supportare un setup di localizzazione in stile' gettext', comunque. Sono più preoccupato per la scalabilità, le prestazioni e le migliori pratiche di cui potrei non essere a conoscenza. – EAMann

+0

'GetAttributeValue' non è un metodo di estensione contrario al testo della descrizione precedente. –

risposta

13

Questo è lo stesso metodo che utilizzo. L'unico lato negativo è la serializzazione. I valori degli attributi personalizzati non vengono serializzati.

mi piace il metodo attributo personalizzato rispetto al metodo del database perché lega i dati degli attributi diritto al enum invece di dover utilizzare una tabella di ricerca o di classe, ecc

+1

L'altro lato negativo è che è necessario ridistribuire completamente l'applicazione se una descrizione cambia mai tanto quanto un personaggio: – eouw0o83hf

+1

@ eouw0o83hf: true. mitigato dalle recenti opzioni di implementazione (aka ClickOnce), ma tu sei corretto. La maggior parte delle mie app tendono ad essere web o cose con lunghi periodi tra i cicli di distribuzione in cui molte altre cose cambieranno, quindi aggiornare le descrizioni di coppia non è un grosso problema. –

1

È possibile modificare il database? Penso che l'opzione migliore sarebbe quella di fare una tabella (o tabelle) per ospitare i possibili valori dell'enumerazione e della chiave esterna gli oggetti principali (invece di usare i codici char - questo lo rende più facile e normalizza il tuo DB) . Assegna al tavolo una colonna Abbreviation e Description, quindi trascina quelli in entrata e fai riferimento ad essi con la loro chiave e memorizzali nella cache se le ricerche sono lente.

Una cosa che è pericolosa per gli attributi è che se qualcuno di quelle stringhe dovesse mai cambiare, si tratta di una ridistribuzione completa dell'app. Se si apportano i valori del database, è possibile modificarli con un semplice UPDATE.

2

probabilmente sarei costruire una tabella di hash e un tipo speciale per qualcosa di simile. Potresti aver già scartato l'idea per un motivo o per un altro, ma ecco cosa non farei conoscere le specifiche della tua applicazione.

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" } }, 
} 

Poi ho potuto facilmente tenere interi nelle mie altre classi per risparmiare memoria, scoprire se un particolare valore era valido controllando per l'esistenza nelle Keys del Dizionario, All That Jazz. Sarebbe probabilmente molto più facile fare il databinding se alla fine userete anche WPF o leggere/scrivere su disco.

Problemi correlati