6

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

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

我的问题是我的 Web 服务的使用者没有枚举的原始常量值。生成的代理类客户端具有相当于此的内容:

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

因此,当消费者检查“读取”访问权限时,即使“testItem”为“完整”,这也是错误的

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

如何通过 Web 服务正确提供标志?

编辑:

根据这篇文章,可能无法做我想做的事情。伊万·克里维亚科夫说

枚举的不完全透明度

事实证明,枚举并不像我们希望的那样透明。存在三个棘手的问题:

  1. 如果服务器端代码声明一个枚举并为其成员分配特定的数值,则这些值对客户端将不可见。
  2. 如果服务器端代码声明了一个带有“复合”掩码值的 [Flags] 枚举(如 White = Red|Green|Blue),则它不会正确反映在客户端。
  3. 如果服务器或客户端传输超出枚举范围的“非法”值,则会在另一端的 XML 反序列化器中引发异常。

所以我想知道这是否只是一个限制,是不可能的。

4

4 回答 4

3

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

如果你的 AccessLevels = Read | 你可以假设完全访问。如果您的 AccessLevels = 0 [无],则写入且无

您的枚举将如下所示:

[Serializable,Flags]
public enum AccessLevels
{
    Read = 1,
    Write = 2
}
于 2009-02-04T01:01:24.387 回答
0

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

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

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

编辑:

我最初的回答建议将值作为单独的 Web 服务而不是在枚举中传递。

但是,四处寻找,似乎 0,1,2 的枚举在 Web 服务中被映射到 1,2,4(即使设置了 [Flags] 属性)是一个常见问题。

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

于 2009-02-03T00:41:29.967 回答
0

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

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

看看它是否效果更好。

(我希望我不要自欺欺人,已经很晚了,我正在去睡觉的路上..)

于 2009-02-03T00:42:15.300 回答
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;
  }
 }
} 

我可以看到的另一个选项是提供一种方法,使用他们使用的任何语言来成功地互操作您发送的整数。flag 运算符意味着 c# 进行位掩码以查找是否标记了单个标志

0001 -> 无
0010 -> 读取
0100 -> 写
0110 -> 满

因此要检查任何权限,您应该查看该位是否已设置


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 的定义,您的客户端将默默地错过行为。

于 2009-02-03T15:00:19.013 回答