8

我们没有将每个权限拆分为单独的列或 sql server 表,而是重新考虑使用Flag属性来Enum与位操作一起使用。我们的应用程序定义了访问资源(读取、修改、更新)的端点(不是来自其他服务的端点),并且每个用户都被授予权限,例如Bob has permissions to Read, Modify resource X,当 bob 访问该资源时,我们检查 bob 是否具有权限 x。现在我们将在哪里应用这很清楚这是我的疑问

  • 假设 Bob 使用标记的枚举对资源具有读、写、删除权限,我会做Permission.Read | Permission.Write | Permission.Delete的最终结果是按位与整数还是另一个枚举?

  • 对于在数据库表中存储此权限,该列应为integer?

  • 如果对问题 1 的回答是,Enum那么我是否应该在Permissions枚举上定义另一个属性,该属性表示位和运算的整数值?

disclaimer:示例中所指的 Bob 不代表 Stack Overflow 站点网络中的任何用户或任何人。这只是另一个角色

4

2 回答 2

10

按顺序回答您的问题:

  • 假设您已经在, 上设置了[Flags]属性并enum使用了正确的运算符(对于按位运算),它基本上两者兼而有之。如果将结果转换为整数,您将获得相关值的按位和,即。7为你的例子。如果您使用,那么您将返回一个字符串,指示该值具有所有三个值。我相信某处有一种方法,但我见过的大多数代码都使用经过验证的真实位代码进行比较,即:&|.ToString()HasFlags()

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

    从技术的角度来看,C# 的类型安全有助于保持理智,并且|ing 或&ing 两个enum相同类型的结果是另一个enum相同类型,但所有enums 都是简单的整数,并且在大多数情况下可以这样处理,尽管有些事情需要明确的转换到/从int

  • 它应该是一个整数类型,是的。我相信枚举的默认类型是Int32,但是如果您想精确匹配数据库和代码,您可以明确设置它。

  • 鉴于以上所有情况,为常用权限集(例如ReadWrite. 特别是,NoneMicrosoft 建议所有枚举都使用一个元素,尤其是当您要转换值时。这允许新初始化变量的后备和有效值以及default(Permissions). 您可以根据其他值在枚举中设置值,如下所示:

    [Flags]
    enum Permissions {
      None =    0,
      Read =    0x001,
      Write =   0x010,
      Execute = 0x100,
      ReadWrite = Read | Write,
      // [snip]
    }
    
于 2012-04-23T04:58:56.570 回答
5
  1. 用 [Flags] 标记的枚举值的按位 OR/AND 是相同枚举的值。
  2. 整数是合理的归档以将枚举值存储在数据库中。
  3. 不,您不需要添加额外的枚举值,但可以这样做是为了方便。

通常,您使用FlagsAttribute定义此类枚举,即

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

当以这种方式定义时,您可以将不同的值与 | (或)操作:

My readAndWrite = My.Read | My.Write;

按位 AND 将为您提供 0 表示唯一标志的枚举值,但通常用于屏蔽其他位:

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

请注意,逻辑 AND (&&) 不能应用于枚举值。

于 2012-04-23T04:57:21.230 回答