2009-02-03 19 views
6

que tienen una enumeración de atributos bandera que está detrás de un servicio web de la siguiente manera:banderas con los servicios web

[Serializable,Flags] 
public enum AccessLevels 
{ 
    None = 0, 
    Read = 1, 
    Write = 2, 
    Full = Read | Write 
} 

Mi problema es el consumo de mi servicio web no tiene los valores constantes originales de la enumeración. El lado del cliente clase proxy resultante tiene algo que equivale a esto:

{ 
    None = 1, 
    Read = 2, 
    Write = 4, 
    Full = 8 
} 

Y así, cuando el consumidor está verificando "lectura" que esto es falso, incluso cuando "TestItem" es "completo"

((testItem & Svc.Read) == Svc.Read) 

¿Cómo puedo proporcionar banderas correctamente sobre un servicio web?

EDIT:

De acuerdo con el artículo this puede que no sea posible hacer lo que estoy buscando hacer. Ivan Krivyakov afirma

imperfecta Transparencia de enumeraciones

Resulta que las enumeraciones no son tan transparente como nos gustaría que fueran. Hay tres temas pegajosos:

  1. Si el código del lado del servidor declara una enumeración y asigna valores específicos numéricos a sus miembros, estos valores no serán visibles para el cliente.
  2. Si el código del lado del servidor declara un [Banderas] enumeración con "compuesto" enmascarar valores (como en Blanco = Rojo | Green | Azul), no se refleja adecuadamente en el lado cliente.
  3. Si el servidor o el cliente transmite un valor "ilegal" que está fuera de el alcance de la enumeración, provoca una excepción en XML de-serializer en el del otro lado.

Así que me pregunto si esto es solo una limitación y no es posible.

Respuesta

3

He realizado una investigación exhaustiva sobre esto y he descubierto que no es posible serializar las constantes de enumeración a través de un servicio web. Tenga en cuenta que para lograr su objetivo no necesita las enumeraciones None o Full. Estas dos enumeraciones pueden estar implícitas con la combinación de lectura/escritura:

Puede asumir el acceso total si AccessLevels = Read | Escribe y ninguno si sus AccessLevels = 0 [nada]

Sus enumeraciones se vería así:

[Serializable,Flags] 
public enum AccessLevels 
{ 
    Read = 1, 
    Write = 2 
} 
+0

Estoy pensando que esta es la ruta que puedo tomar aquí. Sin embargo, me gustaría poder tener la opción "Ninguno" explicada para mis usuarios. – Brawndo

0

Tuve un problema similar y lo solucioné agregando otro servicio web para devolver primero los valores de bandera en cursiva.

Esos entonces se convirtieron en los valores que utilicé en la comparación.

Puede que no sea la solución más limpia, pero funciona.

Editar:

Mi respuesta original sugirió que los valores se transmiten a través como un servicio web independiente y no dentro de una enumeración.

Sin embargo, parece que una enumeración de 0,1,2 siendo mapeada a 1,2,4 a través de un servicio web (incluso si el atributo [Flags] está configurado) es un problema común.

La solución sugerida por varias personas es modificar la definición de enumeración original y comenzar desde 1 en lugar de 0.

+0

Nos puedes contar un poco? – Brawndo

0

Las banderas deben ser múltiplos de dos, y en su caso sus banderas son (0,1,2,3). Trate de cambiar la definición de la estructura a:

[Serializable,Flags] 
public enum AccessLevels{  
None = 1,  
Read = 2,  
Write = 4,  
Full = Read | Write} 

Y ver si funciona mejor.

(espero que no estoy haciendo el tonto, es tarde y estoy en mi camino a la cama ..)

+0

Eso todavía no funciona. He visto este problema antes Con la numeración que ha mencionado el consumidor todavía se vea lo siguiente: AccessLevels public enum { Ninguno = 2, Comentario = 8, = 1, Lectura = 4, completa} – Rorzilla

+0

@Rorzilla sí que es de hecho el caso todavía. @Stefan Puedo "arreglarlo" eliminando "Completo" y "Ninguno", luego la clase de proxy se convertirá en Lectura = 1 y Escritura = 2, pero aún así quisiera proporcionar al usuario la opción de ninguno para que no lo haga tiene que "solo saber" algo y no tiene que usar un valor de 0 – Brawndo

+1

@Stefan - No, las banderas deben ser bits individuales, de los cuales 1 es el primero. Ninguno debe * siempre * definirse como 0 porque eso significa que no hay bits establecidos. Si ninguno = 1, entonces, ¿qué es 0? ¿Realmente no? –

0

Una opción sería la de proporcionar una clase más detallado en lugar de la enumeración, por ejemplo,

[Serializable] 
public class AccessPermission{ 
public boolean None{get;set;} 
public boolean Read{get;set;} 
public boolean Write{get;set;} 
public boolean Full{get;set;} 

public AccessPermission(AccessLevels level){ 
    None = false; 
    Read = false; 
    Write = false; 
    Full = false; 

    switch(level){ 
    case AccessLevels.None: 
    break; 
    case AccessLevels.Read: 
    Read = true; 
    break; 
    case AccessLevels.Write: 
    Write = true; 
    break; 
    case AccessLevels.Full: 
    Read = true; 
    Write = true; 
    Full = true; 
    break; 
    } 
} 
} 

La otra opción que veo es proporcionar un método en lo que cada vez el lenguaje que utilizan para interoperar con éxito el número entero que está enviando. El operador de la bandera significa que C# bit de enmascaramiento de encontrar si una bandera individuo está marcado

 
0001 -> None 
0010 -> Read 
0100 -> Write 
0110 -> Full 

modo para comprobar si el permiso se debe ver si ese bit se pone


public static boolean CanRead(int accessLevel){ 
return (accessLevel | 2) > 0 // return true if read bit set, using bitwise or 
} 

public static boolean CanWrite(int accessLevel){ 
return (accessLevel | 4) > 0 // return true of write bit set. 
} 

Tenga en cuenta esta segunda solución es más frágil, si cambia la definición de accessLevels, su cliente se comportará de forma silenciosa.