当位掩码(标志)枚举变得太大时该怎么办
我的应用程序中有一组非常大的权限,我用 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
}
I have a very large set of permissions in my application that I represent with a Flags enumeration. It is quickly approaching the practical upper bound of the long data type. And I am forced to come up with a strategy to transition to a different structure soon. Now, I could break this list down into smaller pieces, however, this is already just a subset of the overall permissions for our application, based on our applications layout. We use this distinction extensively for display purposes when managing permissions and I would rather not have to revisit that code at this time if I can avoid it.
Has anybody else run into this issue? How did you get past it? General examples are fine, but I am most interested in a c# specific example if there are any language specific tricks that I can employ to get the job done.
May not be neccessary, but here is the list of Permissions currently defined for the portion of the app I am dealing with.
//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
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我在那里看到了至少几个不同枚举的值...
我的第一个想法是通过将权限拆分为逻辑组来解决问题(
RuleGroupPermissions
、RulePermissions
、LocationPermissions
、...),然后使用一个类 (WebAgentPermissions
) 公开每个权限枚举类型的属性。由于权限值看起来是重复的,因此您最终可能会使用单个枚举:
然后让 WebAgentPermissions 类为要设置权限的每个区域公开一个属性;
I see values from at least a handful of different enumerations in there...
My first thought was to approach the problem by splitting the permissions up in logical groups (
RuleGroupPermissions
,RulePermissions
,LocationPermissions
, ...), and then having a class (WebAgentPermissions
) exposing a property for each permission enum type.Since the permission values seem repetitive, you could probably get away with a single enum in the end:
And then have the
WebAgentPermissions
class expose a property for each area where permissions are to be set;语言文档说:
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 只是默认数据类型! 事实上你可以指定Int64。
...最多允许 64 个值。 但这似乎是最大的,之后你将考虑重新设计。 由于不太了解您的解决方案的其余部分,我无法确切地说出什么可能适合。 但特权标识符数组(或哈希映射)可能是最自然的方法。
Language documentation says:
http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx
"The underlying type is Int32 and so the maximum single bit flag is 1073741824 and obviously there are a total of 32 flags for each enum."
However... UPDATED:
Commenter is correct. Check out this:
http://msdn.microsoft.com/en-us/library/ms182147(VS.80).aspx
Int32 is only the DEFAULT datatype! In fact you can specify Int64.
...allowing up to 64 values. But that certainly seems to be the maximum, after that you're going to be looking at re-engineering. Without knowing too much about the rest of your solution, I can't say exactly what might suit. But an array (or hash-map) of privilege identifiers is probably the most natural approach.
不是对您问题的答案,而是相关的建议:我们使用位移来指定数值,如下所示:
对于前十个不太重要,但之后它变得非常方便。
Not an answer to your question, but a related suggestion: we use bitshifting to specify the numeric values, like so:
Not so important for the first ten, but after that it gets really handy.
事实证明,这是一个比我想象的更常见的问题,我将 CSS 类表示为标志类型,并且存在超过 64 种可能性。 我从这个过程中学到了所有东西,并将其转变为可重用的模式,尽管因为它是一个结构,但它是一个复制粘贴类型的模式。
这是 BigFlags“枚举类型”。 它使用
System.Numerics
中的BigInteger
,或者如果您无法引用该程序集,则可以使用BitArray
进行回退只需关闭NUMERICS
预处理器指令即可。它的行为非常像
Flags
枚举,甚至定义诸如HasFlag(...)
、GetNames()
、GetValues( )
、TryParse(...)
、TypeConverter
、IConvertible
等。因为它确实定义了TypeConverter
和IConvertible
,它也适合存储在数据存储中,尽管始终作为字符串或文本数据类型。您将“enum”值公开为
public static readonly
成员。 组合枚举值作为仅获取属性公开。要使用它,请复制并粘贴代码,然后进行搜索并将
BigFlags
替换为您的结构名称,然后删除TODO
部分中的枚举并添加您的值。希望有人觉得它有用。
This turned out to be a more common problem than I thought it would be, where I was representing CSS classes as flags types and there were more than 64 possibilities. I've taken all I learned from that process and turned it into a reusable pattern, albeit since it's a struct, it's a copy-and-paste type pattern.
This is the
BigFlags
"enumerated type". It uses eitherBigInteger
fromSystem.Numerics
, or if there is no way you can reference that assembly, there is a fallback that usesBitArray
by simply turning off theNUMERICS
preprocessor directive.It behaves remarkably like a
Flags
enum, even defining such things asHasFlag(...)
,GetNames()
,GetValues()
,TryParse(...)
, aTypeConverter
,IConvertible
, etc. Since it does define aTypeConverter
andIConvertible
, it's also suitable for storing in a data store, albeit always as a string or text data type.You expose the "enum" values as
public static readonly
members. Combined enum values are exposed as get-only properties.To use it, copy and paste the code, then do a search and replace on
BigFlags
with your struct name, then delete the enums in theTODO
section and add your values.Hope somebody finds it useful.
您可以检查 BitArray 类。 也许你将来会用到它。
You can check BitArray class. Maybe you will use it in future.
在 C# 中,表示类似于枚举但更灵活的值的一种灵活方法是将其表示为具有可用预定义值的静态类,如下所示
: 看起来你可以,如果你真的尝试过的话。
In C#, one flexible way to represent a value that is sort of an enumeration but more flexible is to represent it as a static class with precooked values available, like this:
Alternatively, just split the thing up; it looks like you could, if you really tried.
如果我控制这个应用程序,我可能会想出一组通用的权限(查看、添加、编辑、删除、上传/导入)和一组资源(用户、角色、规则等)。 在网页上找到与该页面关联的资源类型,然后检查权限。 也许是这样的:
或者
甚至
您有一些与其他所有内容都没有意义的权限(仅举一个例子,将权限分配给用户)。 由于我对这个问题知之甚少,我不确定如何处理这个问题。
If I were in control of this application, I would probably come up with a common set of permissions (View, Add, Edit, Delete, Upload/Import) and a set of resources (Users, Roles, Rules, etc). On the web page find the resource type associated with that page and then check the permissions. Perhaps something like:
or
or even
You have a couple of permissions that don't make sense with everything else (Assign Permissoins to user, to name one). I'm not sure how I would handle that based on how little I know the problem.
我没有遇到过这种情况。
这就是我的想法,为每个类别和类别创建单独的枚举。 接受这些作为参数。
编辑:看看 messagebox.show 是如何做到的。 OK、OKCancel 与问题、信息、感叹分开。
I have not been in this situation.
Here is what I think, create separate enums for each of the category & accept those as parameters.
EDIT: Look at how messagebox.show does it. OK, OKCancel separated from Question, Information, Exclamation.
对于面临类似问题的其他人,我建议 InfiniteEnumFlags 库,
它具有所有 dotnet 枚举标志功能以及更多功能。
For others facing a similar problem, I suggest InfiniteEnumFlags library,
it has all of the dotnet enum flags features and more.
怎么样...在列表中拥有权限?
它们可以在程序启动时从数据库加载,并且无需重新部署系统即可进行修改!
How about... having the permissions in a list?
They can be loaded from a database when the program starts, and modified without redeploying the system!