标志与Web服务

时间:2009-02-03 00:36:12

标签: c# .net web-services flags

我在Web服务后面有一个标志属性枚举,如下所示:

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

我的问题是我的网络服务的消费者没有枚举的原始常量值。生成的代理类客户端有一些相当于:

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

因此,当消费者检查“读取”访问时,即使“testItem”为“Full”,这也将是假的

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

如何在Web服务上正确提供标记?

编辑:

根据this文章,我可能无法做我想做的事情。 Ivan Krivyakov表示

  

枚举的透明度不足

     

事实证明,枚举并非如此   我们希望它们是透明的。   有三个棘手的问题:

     
      
  1. 如果服务器端代码声明枚举并分配特定数字   值为其成员,这些值   将不会被客户看到。
  2.   
  3. 如果服务器端代码使用“复合”掩码声明[Flags]枚举   值(如白色=红色|绿色|蓝色),   它没有正确反映在   客户方。
  4.   
  5. 如果服务器或客户端发送的“非法”值超出   枚举的范围,它导致了   XML反序列化器中的异常   另一边。
  6.   

所以我想知道这是否只是一种限制而且是不可能的。

4 个答案:

答案 0 :(得分:3)

我对此进行了大量研究,发现无法通过Web服务序列化枚举常量。请注意,要实现目标,您不需要枚举None或Full。这两个枚举可以用读/写组合暗示:

如果您的AccessLevels = Read |,您可以假设完全访问权限写    如果您的AccessLevels = 0 [无]

,则无

您的枚举将如下所示:

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

答案 1 :(得分:0)

我遇到了类似的问题,并通过添加另一个Web服务来首先返回当前标志值。

然后那些成为我在比较中使用的值。

可能不是最干净的解决方案,但它有效。

编辑:

我的原始答案建议将值作为单独的Web服务传递,而不是在枚举中传递。

但是,看起来,在Web服务中映射到1,2,4的枚举0,1,2(即使设置了[Flags]属性)也是一个常见问题。

许多人建议的解决方案是修改原始枚举定义并从1而不是0开始。

答案 2 :(得分:0)

标志应为2的倍数,在您的情况下,标志为(0,1,2,3)。 尝试将结构的定义更改为:

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

看看它是否更好。

(我希望我不是自欺欺人,迟到了,我正在去床上的路上......)

答案 3 :(得分:0)

一种选择是提供更详细的类而不是枚举,例如

[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;
  }
 }
} 

我能看到的另一个选项是提供一种方法,用它们用什么语言来成功地互操作你发送的整数。标志运算符意味着c#进行位屏蔽以查找是否标记了单个标志

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

所以要检查是否有任何权限,你应该看看该位是否已设置


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.
}

请注意,第二个解决方案更加脆弱,如果您更改了accessLevels的定义,则客户端将默默地忽略该行为。