【问题标题】:Enums to define permission sets in c#在 C# 中定义权限集的枚举
【发布时间】:2012-05-03 17:35:15
【问题描述】:

我们正在重新考虑将Flag 属性用于Enum,而不是将每个权限拆分为单独的列或sql server 表,以用于按位操作。我们的应用程序定义了访问资源(读取、修改、更新)的端点(不是来自其他服务的端点),并且每个用户都被授予权限,例如 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 网站的任何用户或任何人。这只是另一个角色

【问题讨论】:

    标签: c# .net permissions enums flags


    【解决方案1】:
    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;
    

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

    【讨论】:

    • +1 整洁你们俩都帮助了我如果无论如何我都可以将两者都标记为答案,Gosh 现在没有这样的功能。我会支持你
    【解决方案2】:

    按顺序回答您的问题:

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

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

      从技术角度来看,C# 的类型安全有助于保持理智,|ing 或 &ing 两个相同类型的 enums 的结果是另一个相同类型的 enum,但都是 @987654332 @s 只是整数,在大多数情况下可以这样处理,尽管有些事情需要显式转换为 int

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

    • 鉴于以上所有情况,为常用权限集设置预定义值仍然很有意义,例如ReadWrite。特别是,Microsoft 建议对所有枚举使用 None 元素,尤其是在您要转换值时。这允许新初始化变量的回退和有效值以及default(Permissions) 的合理值。您可以根据其他值在枚举中设置值,如下所示:

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

    【讨论】:

    • @Mathhew 只是在我脑海中将按位或的结果作为整数存储在表中。我应该如何在应用程序中进行许可检查。在这里用代码if (IntegerFromDb == Permissions.Read) { print "Success!"; } 应该我将 Integer 解析为 Permissions 类型的 Enum 并进行检查?
    • @Deeptechtons:您可以轻松地将任何整数转换回枚举类型:var perms = (Permissions)IntegerFromDb。这是最安全的方法,但是我认为您可以直接与我上面包含的代码进行比较而无需强制转换。始终将& 与预期值进行比较,尤其是在使用建议的ReadWrite 之类的组合值时,因为有可能只有一个而不是另一个,从而欺骗!= None 样式检查。
    • @Deeptechtons:请务必阅读我在第 3 点中关于枚举的合理值的注释。如果将整数转换为对给定值没有意义的枚举,C# 可能会出现一些糟糕的情况。
    • 这是否意味着我这样做Permission.Read | Permission.Write 并且结果整数在 Permissions 枚举中没有等效的整数值,然后它默认为 None (如#3)
    • @Deeptechtons:不,这意味着它等同于Permission.Read | Permission.Write,正如预期的那样。但是您试图将 9 投射到我提供的枚举中,它不会很好地工作。我不是 100%,但我认为它甚至可能会抛出异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 2011-01-10
    相关资源
    最近更新 更多