2012-04-23 13 views
8

En lugar de dividir cada permiso en columnas individuales o en tablas de servidor sql, estamos reconsiderando el uso del atributo Flag en Enum para utilizarlo con operaciones de bits. Nuestra aplicación define los puntos finales (no el de los servicios de descanso) para acceder a los recursos (leer, modificar, actualizar) y cada usuario tiene derecho a permisos, por ejemplo, Bob has permissions to Read, Modify resource X, cuando bob entra y accede a este recurso, verificamos si bob tiene permiso x.Now que, cuando vamos a aplicar esto está claro que aquí están mis dudasEnumeraciones para definir conjuntos de permisos en C#

  • Supongamos que Bob tiene de lectura, escritura, eliminar el permiso de recurso mediante enumeraciones marcados yo haría Permission.Read | Permission.Write | Permission.Delete es el resultado final de bits AND de una entero u otro Enum?

  • Para almacenar este permiso en la tabla de la base de datos ¿debería la columna ser integer?

  • Si la respuesta a la pregunta 1 es Enum, ¿debería definir otra propiedad en la enumeración Permissions que represente el valor entero de Bit wise y la operación?

disclaimer: el Bob se hace referencia en el ejemplo no representa ningún usuario en la red de sitios de desbordamiento de pila o cualquier persona. Es solo otro carácter

Respuesta

10

para responder a sus preguntas en orden:

  • Suponiendo que haya configurado el atributo [Flags] en el enum, y utilizar el operador correcto (& y | para operaciones bit a bit) que, esencialmente, es a la vez. Si arroja el resultado a un número entero, obtendrá los valores relevantes, es decir, bit a bit. 7 para tu ejemplo. Si usa .ToString(), obtendrá una cadena hacia atrás que indica que el valor tiene los tres valores.Creo que hay un método HasFlags() alguna parte, pero la mayoría del código que he visto utiliza el código probado y verdadero bit a bit para las comparaciones, es decir:

    var x = Permissions.Read | Permissions.Write; 
    if ((x & Permissions.Read) == Permissions.Read) { print "Success!"; } 
    

    Desde un punto de vista técnico, el tipo de seguridad de C# 's ayuda a mantener las cosas en su sano juicio y el resultado de | ing 0 enum s del mismo tipo es enum del mismo tipo pero todos enum s son simplemente enteros, y se pueden tratar como tales en la mayoría de los casos, aunque algunas cosas necesitan moldes explícitos a/desde int.

  • Debe ser un tipo integral, sí. Creo que el tipo predeterminado para una enumeración es Int32; sin embargo, puede establecerlo explícitamente si desea hacer coincidir exactamente la base de datos y el código.

  • Dado todo lo anterior, todavía puede tener mucho sentido tener valores predefinidos para los conjuntos de permisos comúnmente utilizados, por ejemplo ReadWrite. En particular, Microsoft recomienda un elemento None para todas las enumeraciones, especialmente si va a emitir valores. Esto permite un retorno y un valor válido para las variables recién inicializadas, así como un valor razonable para default(Permissions). Puede establecer valores en su enumeración basada en otros de esta manera:

    [Flags] 
    enum Permissions { 
        None = 0, 
        Read = 0x001, 
        Write = 0x010, 
        Execute = 0x100, 
        ReadWrite = Read | Write, 
        // [snip] 
    } 
    
+0

@Mathhew justo fuera de mi cabeza Almacenar el resultado de O bit a bit en la tabla como un entero. ¿Cómo debo hacer mi verificación de permiso en la aplicación? hablando en código aquí 'if (IntegerFromDb == Permissions.Read) {print" ¡Correcto! "; } 'debería ** analizar el Entero a Enum de tipo Permisos ** y hacer el control? – Deeptechtons

+0

@Deeptechtons: Puedes convertir fácilmente cualquier entero al tipo de enumeración: 'var perms = (Permissions) IntegerFromDb'. Esta es la forma más segura, sin embargo, creo que es posible que pueda comparar directamente con el código que he incluido anteriormente sin un reparto. Siempre compare el 'y' con el valor esperado, especialmente si usa valores combinados como el 'ReadWrite' sugerido porque es posible tener uno y no el otro y engañar a una verificación de estilo'! = None'. –

+0

@Deeptechtons: Asegúrese de leer mis notas en el punto n. ° 3 acerca de los valores de sanación para las enumeraciones. C# puede jugar algo horrible si lanzas un entero a una enumeración que no tiene sentido para el valor dado. –

5
  1. O BIEN Y AND para valores de enum marcados con [Banderas] son ​​valores de la misma enumeración.
  2. Entero es razonable archivado para almacenar los valores enum en la base de datos.
  3. No, no necesita agregar valores enum adicionales, pero puede hacerlo para conveniencia.

Normaly que definen a dichos enumeraciones con FlagsAttribute decir

[Flags] enum My { 
    None = 0, Read =1, Write =2, Delete = 4 
}; 

Cuando define de esta manera se pueden combinar con diferentes valores | (O) la operación:

My readAndWrite = My.Read | My.Write; 

AND bit a bit le dará 0 para valores de enumeración que representan las banderas únicas, pero comúnmente utilizado para enmascarar otros bits:

bool doIHaveWrite = (readAndWrite & My.Write) == My.Write; 

Tenga en cuenta que lógica Y (& &) puede no se aplicará a los valores enum.

+2

+1 ordenadas ustedes dos me han ayudado Si había alguna forma de marcar tanto como respuestas, Gosh ninguna función como tal en SO ahora. Voy a votarte – Deeptechtons