位掩码(标志)枚举变得太大时该怎么办

时间:2009-06-29 21:50:50

标签: c# permissions enums types bitmask

我的应用程序中有一组非常大的权限,我使用Flags枚举表示。它正在快速接近长数据类型的实际上限。我不得不提出一个战略,很快就会转变为一个不同的结构。现在,我可以将此列表分解为更小的部分,但是,根据我们的应用程序布局,这已经只是我们应用程序的总体权限的一部分。我们在管理权限时广泛使用这种区别用于显示目的,如果我可以避免,我宁愿不必重新访问该代码。

还有其他人遇到过这个问题吗?你是怎么过去的?一般的例子都很好,但是我最感兴趣的是一个c#特定的例子,如果有任何语言特定的技巧可以用来完成工作。

可能不是必需的,但这是当前为我正在处理的应用程序部分定义的权限列表。

//Subgroup WebAgent
[Flags]
public enum WebAgentPermission : long
{
    [DescriptionAttribute("View Rule Group")]
    ViewRuleGroup = 1,
    [DescriptionAttribute("Add Rule Group")]
    AddRuleGroup = 2,
    [DescriptionAttribute("Edit Rule Group")]
    EditRuleGroup = 4,
    [DescriptionAttribute("Delete Rule Group")]
    DeleteRuleGroup = 8,
    [DescriptionAttribute("View Rule")]
    ViewRule = 16,
    [DescriptionAttribute("Add Rule")]
    AddRule = 32,
    [DescriptionAttribute("Edit Rule")]
    EditRule = 64,
    [DescriptionAttribute("Delete Rule")]
    DeleteRule = 128,
    [DescriptionAttribute("View Location")]
    ViewLocation = 256,
    [DescriptionAttribute("Add Location")]
    AddLocation = 512,
    [DescriptionAttribute("Edit Location")]
    EditLocation = 1024,
    [DescriptionAttribute("Delete Location")]
    DeleteLocation = 2048,
    [DescriptionAttribute("View Volume Statistics")]
    ViewVolumeStatistics = 4096,
    [DescriptionAttribute("Edit Volume Statistics")]
    EditVolumeStatistics = 8192,
    [DescriptionAttribute("Upload Volume Statistics")]
    UploadVolumeStatistics = 16384,
    [DescriptionAttribute("View Role")]
    ViewRole = 32768,
    [DescriptionAttribute("Add Role")]
    AddRole = 65536,
    [DescriptionAttribute("Edit Role")]
    EditRole = 131072,
    [DescriptionAttribute("Delete Role")]
    DeleteRole = 262144,
    [DescriptionAttribute("View User")]
    ViewUser = 524288,
    [DescriptionAttribute("Add User")]
    AddUser = 1048576,
    [DescriptionAttribute("Edit User")]
    EditUser = 2097152,
    [DescriptionAttribute("Delete User")]
    DeleteUser = 4194304,
    [DescriptionAttribute("Assign Permissions To User")]
    AssignPermissionsToUser = 8388608,
    [DescriptionAttribute("Change User Password")]
    ChangeUserPassword = 16777216,
    [DescriptionAttribute("View Audit Logs")]
    ViewAuditLogs = 33554432,
    [DescriptionAttribute("View Team")]
    ViewTeam = 67108864,
    [DescriptionAttribute("Add Team")]
    AddTeam = 134217728,
    [DescriptionAttribute("Edit Team")]
    EditTeam = 268435456,
    [DescriptionAttribute("Delete Team")]
    DeleteTeam = 536870912,
    [DescriptionAttribute("View Web Agent Reports")]
    ViewWebAgentReports = 1073741824,
    [DescriptionAttribute("View All Locations")]
    ViewAllLocations = 2147483648,
    [DescriptionAttribute("Access to My Search")]
    AccessToMySearch = 4294967296,
    [DescriptionAttribute("Access to Pespective Search")]
    AccessToPespectiveSearch = 8589934592,
    [DescriptionAttribute("Add Pespective Search")]
    AddPespectiveSearch = 17179869184,
    [DescriptionAttribute("Edit Pespective Search")]
    EditPespectiveSearch = 34359738368,
    [DescriptionAttribute("Delete Pespective Search")]
    DeletePespectiveSearch = 68719476736,
    [DescriptionAttribute("Access to Search")]
    AccessToSearch = 137438953472,
    [DescriptionAttribute("View Form Roles")]
    ViewFormRole = 274877906944,
    [DescriptionAttribute("Add / Edit Form Roles")]
    AddFormRole = 549755813888,
    [DescriptionAttribute("Delete UserFormRolesDifferenceMasks")]
    DeleteFormRole = 1099511627776,
    [DescriptionAttribute("Export Locations")]
    ExportLocations = 2199023255552,
    [DescriptionAttribute("Import Locations")]
    ImportLocations = 4398046511104,
    [DescriptionAttribute("Manage Location Levels")]
    ManageLocationLevels = 8796093022208,
    [DescriptionAttribute("View Job Title")]
    ViewJobTitle = 17592186044416,
    [DescriptionAttribute("Add Job Title")]
    AddJobTitle = 35184372088832,
    [DescriptionAttribute("Edit Job Title")]
    EditJobTitle = 70368744177664,
    [DescriptionAttribute("Delete Job Title")]
    DeleteJobTitle = 140737488355328,
    [DescriptionAttribute("View Dictionary Manager")]
    ViewDictionaryManager = 281474976710656,
    [DescriptionAttribute("Add Dictionary Manager")]
    AddDictionaryManager = 562949953421312,
    [DescriptionAttribute("Edit Dictionary Manager")]
    EditDictionaryManager = 1125899906842624,
    [DescriptionAttribute("Delete Dictionary Manager")]
    DeleteDictionaryManager = 2251799813685248,
    [DescriptionAttribute("View Choice Manager")]
    ViewChoiceManager = 4503599627370496,
    [DescriptionAttribute("Add Choice Manager")]
    AddChoiceManager = 9007199254740992,
    [DescriptionAttribute("Edit Chioce Manager")]
    EditChoiceManager = 18014398509481984,
    [DescriptionAttribute("Delete Choice Manager")]
    DeleteChoiceManager = 36028797018963968,
    [DescriptionAttribute("Import Export Choices")] //57
    ImportExportChoices = 72057594037927936
}

8 个答案:

答案 0 :(得分:33)

我在那里看到至少少数不同枚举的价值......

我的第一个想法是通过在逻辑组(RuleGroupPermissionsRulePermissionsLocationPermissions,...)中分割权限来解决问题,然后拥有一个类({{ 1}})为每个权限枚举类型公开一个属性。

由于权限值似乎重复,因此最终可能会使用单个枚举:

WebAgentPermissions

然后让[Flags] public enum Permissions { View = 1, Add = 2, Edit = 4, Delete = 8 } 类为要设置权限的每个区域公开一个属性;

WebAgentPermissions

答案 1 :(得分:17)

语言文档说:

http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx

“底层类型是Int32,因此最大单位标志是1073741824,显然每个枚举总共有32个标志。”

然而......更新:

评论者是对的。看看这个:

http://msdn.microsoft.com/en-us/library/ms182147(VS.80).aspx

Int32只是DEFAULT数据类型!实际上,您可以指定Int64。

public enum MyEnumType : Int64

...允许最多64个值。但这肯定是最大的,之后你会考虑重新设计。在不了解您的其他解决方案的情况下,我无法确切地说出可能适用的内容。但是特权标识符的数组(或哈希映射)可能是最自然的方法。

答案 2 :(得分:13)

您可以查看BitArray课程。也许你将来会用它。

答案 3 :(得分:7)

事实证明这是一个比我想象的更常见的问题,我将CSS类表示为标志类型,并且有超过64种可能性。我已经从这个过程中学到了所有东西,并把它变成了一个可重用的模式,虽然它是一个结构,但它是一个复制粘贴类型的模式。

这是BigFlags“枚举类型”。它使用来自BigInteger的{​​{1}},或者如果您无法引用该程序集,则只需关闭System.Numerics预处理程序指令即可使用BitArray的回退

它的行为与NUMERICS枚举非常相似,甚至可以定义FlagsHasFlag(...)GetNames()GetValues()TryParse(...)等内容,TypeConverter等。因为它确实定义了IConvertibleTypeConverter,所以它也适合存储在数据存储中,尽管总是作为字符串或文本数据类型。

您将“枚举”值公开为IConvertible成员。组合的枚举值将作为只读属性公开。

要使用它,请复制并粘贴代码,然后在public static readonly上搜索并替换您的结构名称,然后删除BigFlags部分中的枚举并添加您的值。

希望有人觉得它很有用。

TODO

答案 4 :(得分:5)

在C#中,一种表示枚举但更灵活的值的灵活方法是将其表示为具有预煮值的静态类,如下所示:

public sealed class WebAgentPermission
{
    private long ID;

    public static readonly WebAgentPermission
        ViewRuleGroup = new WebAgentPermission { ID = 1 };
    public static readonly WebAgentPermission
        AddRuleGroup  = new WebAgentPermission { ID = 2 };

    private WebAgentPermission() { } 

    // considerations: override equals/gethashcode, probably override tostring,
    // maybe implicit cast to/from long, maybe other stuff
}

或者,只是将事情分开;如果你真的尝试的话,看起来你可以。

答案 5 :(得分:4)

如果我控制了这个应用程序,我可能会想出一组共同的权限(查看,添加,编辑,删除,上传/导入)和一组资源(用户,角色,规则等) 。在网页上找到与该页面关联的资源类型,然后检查权限。也许是这样的事情:

Permissions perms = agent.GetPermissions(ResourceType.User);
if((perms & Permissions.View) == Permissions.View) { /* do work */ }

Permissions perms = agent.Permissions[ResourceType.User];
if((perms & Permissions.View) == Permissions.View) { /* do work */ }

甚至

if(agent.IsAuthorized(ResourceType.User, Permissions.View)) { /* do work */ }

你有一些权限对其他一切都没有意义(将Permissoins分配给用户,命名一个)。我不知道如何根据我对问题的了解程度来处理这个问题。

答案 6 :(得分:2)

不是您的问题的答案,而是一个相关的建议:我们使用位移来指定数值,如下所示:

[Flags]
public enum MyEnumFlags : Int64
{
    None = 0,
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    D = 1 << 3,
    E = 1 << 4,
    F = 1 << 5,
    ...etc...

对于前十个而言并不那么重要,但是在此之后它真的很方便。

答案 7 :(得分:1)

我没有遇到过这种情况。

以下是我的想法,为每个类别创建单独的枚举。接受那些作为参数。

RuleGroupPermission
    None = 0
    ViewRuleGroup = 1,
    AddRuleGroup = 2,
    EditRuleGroup = 4,
    DeleteRuleGroup = 8,

LocationOperations
    None = 0
    Add = 1
    View = 2
    Delete = 4

void setPermission(RuleGroupPermission ruleGroupOpsAllowed, LocationOperations locationOptions)
{
   ...
}

编辑:看看messagebox.show是如何做到的。好的,OKCancel与问题,信息,感叹号分开。