2010-07-08 9 views
8

En el código en el trabajo, tenemos muchos usos de las cuerdas mágicas como el siguiente fragmento de código:.Net - estrategias para evitar la cadena mágica

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

lo que hay muchos lugares en los que pasar una cadena como parámetro para ver si el usuario tiene un derecho específico. No me gusta porque eso genera muchas cadenas mágicas.

¿Cuál sería una mejor manera de hacerlo?

Enum, Constant, clase?

Respuesta

17

En ese caso específico, use un Enum. No habrá cadenas mágicas y si Enum cambia (de una manera que rompa la solución de cadenas mágicas), la aplicación ya no se compilará.

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

, entonces solo puede tener:

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

También es posible usar una clase, pero luego se limite cuando se trata de situaciones más complejas. Por ejemplo, un simple cambio de la enumeración a algo como:

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

le permitiría utilizar operadores de bits de permisos más complejas (por ejemplo, una situación en la que un usuario necesita o bien crear o eliminar):

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

Dependiendo de los requisitos de esto también se puede convertir en un banderas-enumeración, es decir, donde los valores se pueden combinar usando '|', por ejemplo mediante el uso de la 0x1 valores , 0x2, 0x4, etc ... –

+1

Buena respuesta y mi respuesta fue idéntica. Debo añadir que el objetivo de un 'enum' es crear una" lista enumerada "de constantes. Agrupar constantes donde se pueden enumerar de esta manera es una gran idea y le da al programa un flujo más lógico también. – Armstrongest

+0

En caso de que también se requiera una representación de cadena, p. para almacenar el conjunto de permisos de una manera legible por humanos, puede simplemente llamar a 'ProfilePermissions.View.ToString()' para obtener la cadena "Ver", o si necesita una representación de cadena personalizada, puede agregar un adorno * Descripción * atributo como se describe aquí: http://blogs.msdn.com/b/abhinaba/archive/2005/10/20/483000.aspx –

0

Puede hacer cadenas constantes en C#.

Se podría definir todas las cuerdas en una cabecera de la siguiente manera:

const string PROFILE_VIEW "Profile.View"; 

No estoy seguro si este es el "mejor", pero es ciertamente mejor que tener valores mágicos en el código.

5

Esto es lo suficientemente común en el marco de .NET también. Los ejemplos son System.Windows.DataFormats y System.Net.WebRequestMethods.Http. Lo que quiere la variedad de sólo lectura:

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

¿Por qué readonly y not const? – sunside

+5

@Markus, si las constantes públicas se utilizan desde un ensamblaje externo, se hornean; si más adelante modifica su constante pública, el ensamblaje externo seguirá utilizando la constante que vio cuando se compiló. –

+1

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

1

crear una clase que fuertemente tipos esas propiedades, como

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

Esto mantendrá sus "cuerdas mágicas" en un lugar dentro de su código. Una enumeración también funcionará, pero no es tan legible en mi opinión.

Nota: mi ejemplo está destinado a actuar como un proxy de propiedad para el usuario conectado, por lo tanto, la clase estática. Si deseaba algo que funcionara con datos más inmediatos (por ejemplo, una lista de usuarios), este tipo de clase tendría que ser no estático e instanciado por cuenta de usuario.

+0

'CanViewProfile' no tiene sentido como una propiedad estática en mi opinión y debería ser un método de instancia en un objeto de usuario. ¿El fragmento sugiere que habría una clase estática para cada usuario? –

+0

No, no estoy sugiriendo una clase estática para cada usuario. La clase anterior solo actúa como un proxy para las propiedades del usuario que ha iniciado sesión. (Utilicé "Alice" porque estoy acostumbrado a usar alice, bob, charlie, david, etc. en lugar de foo/bar. –

0

En segundo lugar el camino mostrado por "Justin Niessner". Pero en algunos casos preferiría escribir siguiendo constructo de código.

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

    } 
    public abstract class Permission 
    { 

    } 
    public class ViewPermission:Permission 
    { 

    } 

y se puede consumir como

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

      } 
3

Los métodos de extensión! Guárdelos en el mismo lugar para realizar un seguimiento de todas las cadenas mágicas.

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

    // etc.. 
} 

A continuación, se puede:

if (user.CanReadProfile()) ..... 
Cuestiones relacionadas