2010-07-08 10 views
8

Nel codice sul posto di lavoro, abbiamo molti usi di stringhe magici come il seguente frammento di codice:.Net - Strategie per evitare stringa magica

if (user.HasRight("Profile.View")) {...} 

Quindi ci sono molti posti dove passiamo una stringa come parametro per vedere se l'utente ha un diritto specifico. Non mi piace perché questo genera molte stringhe magiche.

Quale sarebbe un modo migliore di farlo?

Enum, Constant, classe?

risposta

17

In questo caso specifico, utilizzare un Enum. Non ci saranno stringhe magiche e se l'Enum cambia (in modo tale da rompere la soluzione delle stringhe magiche), l'app non verrà più compilata.

public enum ProfilePermissions 
{ 
    View, 
    Create, 
    Edit, 
    Delete 
} 

allora si può semplicemente avere:

if(user.HasRight(ProfilePermissions.View)) { } 

Si potrebbe anche usare una classe, ma poi ti limiti quando si tratta di scenari più complessi. Per esempio, un semplice cambio di enumerazione a qualcosa come:

public enum ProfilePermissions 
{ 
    View = 1, 
    Create = 2, 
    Edit = 4, 
    Delete = 8 
} 

permetterebbe di utilizzare gli operatori bit a bit per le autorizzazioni più complessi (ad esempio, una situazione in cui un utente ha bisogno creare o Delete):

if(user.HasRight(ProfilePermissions.Create | ProfilePermissions.Delete)); 
+1

A seconda delle esigenze questo può anche essere trasformato in un flag-enum, cioè dove i valori possono essere combinati utilizzando '|', ad esempio utilizzando il 0x1 valori , 0x2, 0x4, ecc ... –

+1

Buona risposta e la mia risposta era identica. Potrei aggiungere che il punto di un 'enum' è quello di creare una" lista enumerata "di costanti. Raggruppare le costanti in cui possono essere elencate come questa è una grande idea e dà al programma anche un flusso più logico. – Armstrongest

+0

Nel caso in cui sia richiesta anche una rappresentazione di stringa, ad es. per memorizzare il set di autorizzazioni in un modo leggibile dall'uomo, puoi semplicemente chiamare 'ProfilePermissions.View.ToString()' per ottenere la stringa "View", o se hai bisogno di una rappresentazione personalizzata della stringa, puoi aggiungere una decorazione * Descrizione * attributo come descritto qui: http://blogs.msdn.com/b/abhinaba/archive/2005/10/20/483000.aspx –

0

È possibile eseguire stringhe costanti in C#.

Si potrebbe definire tutte le stringhe in un colpo di testa in questo modo:

const string PROFILE_VIEW "Profile.View"; 

Non sono sicuro se questo è il modo "migliore", ma la sua certamente meglio che avere valori magici nel codice.

5

Questo è abbastanza comune anche nel framework .NET. Gli esempi sono System.Windows.DataFormats e System.Net.WebRequestMethods.Http. Che ci si vuole la varietà di sola lettura:

public static class MumbleRights { 
    public static readonly string ProfileView = "Profile.View"; 
    // etc.. 
} 
+4

Perché readonly e non const? – sunside

+5

@Markus, se le costanti pubbliche vengono utilizzate da un assieme esterno, vengono cotte in forno; se in seguito cambi la tua costante pubblica, l'assembly esterno continuerà a utilizzare la costante che ha visto al momento della compilazione. –

+1

http://stackoverflow.com/questions/277010/what-are-the-benefits-to-marking-a-field-as-readonly-in-c/312840#312840 –

1

creare una classe che ha fortemente tipi di quelle proprietà, come

public static class UserInfo 
{ 
    public static bool CanViewProfile { get { return User.HasRight("Profile.View"); } } 
} 

Ciò manterrà la vostra "stringhe magiche" in un posto all'interno del codice. Un enum funzionerà anche, ma non è leggibile secondo me.

Nota: il mio esempio è destinato a fungere da proxy di proprietà per l'utente che ha effettuato l'accesso, quindi la classe statica. Se si desidera qualcosa che funzioni su dati più immediati (ad esempio, un elenco di utenti), questo tipo di classe dovrebbe essere non statico e istanziato in base all'account utente.

+0

'CanViewProfile' non ha senso come proprietà statica a mio avviso e dovrebbe piuttosto essere un metodo di istanza su un oggetto utente. Il frammento suggerisce che ci sarebbe una classe statica per ogni utente? –

+0

No, non sto suggerendo una classe statica per ogni utente. La classe sopra fa semplicemente da proxy alle proprietà dell'utente che ha effettuato l'accesso. (Ho usato "Alice" perché sono abituato a usare alice, bob, charlie, david, ecc al posto di foo/bar. –

0

In secondo luogo la via mostrata da "Justin Niessner". Ma in alcuni casi preferirei piuttosto scrivere seguendo il costrutto del codice.

public class User 
    { 
     public Permission Permission { get; set; } 

    } 
    public abstract class Permission 
    { 

    } 
    public class ViewPermission:Permission 
    { 

    } 

e si può consumare come

User user=new User(); 
      if(user.Permission is ViewPermission) 
      { 

      } 
3

metodi di estensione! Tenerli nello stesso posto per tenere traccia di tutte le corde magiche.

public static class UserRightsExtensions { 
    public static bool CanReadProfile(this User user) 
    { 
    return user.HasRight("Profile.View"); 
    } 

    // etc.. 
} 

Quindi è possibile:

if (user.CanReadProfile()) ..... 
Problemi correlati