2010-07-08 3 views
8

Dans le code du travail, nous avons de nombreuses utilisations de cordes magiques comme l'extrait de code suivant:.Net - Stratégies pour éviter chaîne magique

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

Donc il y a beaucoup d'endroits où on passe une chaîne en tant que paramètre voir si l'utilisateur a un droit spécifique. Je n'aime pas ça parce que cela génère beaucoup de chaînes magiques.

Quelle serait une meilleure façon de le faire?

Enum, Constante, classe?

Répondre

17

Dans ce cas spécifique, utilisez un Enum. Il n'y aura pas de chaînes magiques et si l'Enum change (d'une manière qui casserait la solution des chaînes magiques), l'application ne compilera plus.

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

alors vous pouvez simplement avoir:

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

Vous pouvez également utiliser une classe, mais alors vous vous limitez en matière de scénarios plus complexes. Par exemple, un simple changement du Enumeration à quelque chose comme:

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

-vous permettre d'utiliser les opérateurs de bits pour les autorisations plus complexes (par exemple, une situation où un utilisateur a besoin soit créer ou supprimer):

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

En fonction des besoins, cela peut aussi être transformé en drapeaux ENUM, à savoir où les valeurs peuvent être combinées en utilisant '|', par exemple en utilisant les valeurs 0x1 , 0x2, 0x4, etc ... –

+1

Bonne réponse et ma réponse était identique. Je pourrais ajouter que le but d'un 'enum' est de créer une" liste énumérée "de constantes. Regrouper les constantes où elles peuvent être listées comme ceci est une excellente idée et donne au programme un flux plus logique. – Armstrongest

+0

Dans le cas où une représentation sous forme de chaîne est également requise, par ex. pour stocker le jeu d'autorisations d'une manière lisible par l'homme, vous pouvez simplement appeler 'ProfilePermissions.View.ToString()' pour obtenir la chaîne "View", ou si vous avez besoin d'une représentation de chaîne personnalisée, vous pouvez ajouter un adorning * Description * attribut comme décrit ici: http://blogs.msdn.com/b/abhinaba/archive/2005/10/20/483000.aspx –

0

Vous pouvez faire des chaînes constantes en C#.

Vous pouvez définir toutes les chaînes dans un en-tête comme ceci:

const string PROFILE_VIEW "Profile.View"; 

Je ne sais pas si cela est la « meilleure », mais sa certainement mieux que d'avoir des valeurs magiques dans le code.

5

Ceci est également assez commun dans le framework .NET. Les exemples sont System.Windows.DataFormats et System.Net.WebRequestMethods.Http. Vous voudriez la variété readonly:

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

Pourquoi readonly et pas const? – sunside

+5

@Markus, si des constantes publiques sont utilisées à partir d'un assemblage externe, elles sont cuites; Si vous modifiez ultérieurement votre constante publique, l'assembly externe utilisera toujours la constante qu'il a vue lors de sa compilation. –

+1

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

1

Créer une classe fortement ces propriétés types, comme

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

Cela permet de garder vos cordes « magiques » en un seul endroit dans votre code. Une énumération fonctionnera également, mais n'est pas aussi lisible à mon avis.

Remarque: mon exemple est destiné à agir en tant que proxy de propriété pour l'utilisateur connecté, donc la classe statique. Si vous vouliez quelque chose qui fonctionnerait sur des données plus immédiates (par exemple, une liste d'utilisateurs), ce type de classe devrait être non-statique et instancié par compte-utilisateur.

+0

'CanViewProfile' n'a pas de sens en tant que propriété statique à mon avis et devrait plutôt être une méthode d'instance sur un objet utilisateur. L'extrait suggère qu'il y aurait une classe statique pour chaque utilisateur? –

+0

Non, je ne suggère pas une classe statique pour chaque utilisateur. La classe ci-dessus agit uniquement comme un proxy aux propriétés de l'utilisateur connecté. (J'ai utilisé "Alice" parce que je suis habitué à utiliser alice, bob, charlie, david, etc au lieu de foo/bar. –

0

Je seconde comme le montre "Justin Niessner". Mais dans certains cas, je préférerais plutôt écrire la construction de code suivante.

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

    } 
    public abstract class Permission 
    { 

    } 
    public class ViewPermission:Permission 
    { 

    } 

et vous pouvez le consommer comme

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

      } 
3

Méthodes d'extension! Gardez-les au même endroit pour garder une trace de toutes les chaînes magiques.

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

    // etc.. 
} 

Vous pouvez alors:

if (user.CanReadProfile()) ..... 
Questions connexes