web-dev-qa-db-ja.com

ビットマスク(フラグ)列挙型が大きくなりすぎた場合の対処方法

私のアプリケーションには、Flags列挙で表される非常に多くのアクセス許可セットがあります。 longデータ型の実用的な上限にすぐに近づいています。そして、すぐに別の構造に移行するための戦略を考え出す必要があります。これで、このリストをさらに細かく分割できますが、これは既に、アプリケーションのレイアウトに基づいて、アプリケーションの全体的な権限のサブセットにすぎません。権限を管理する際に表示の目的でこの区別を広範囲に使用します。回避できる場合は、現時点でそのコードを再確認する必要はありません。

他の誰かがこの問題に遭遇していますか?どうやってそれを乗り越えたのですか?一般的な例は問題ありませんが、仕事を遂行するために使用できる言語固有のトリックがある場合、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
}
67
Matthew Vines

私はそこに少なくともいくつかの異なる列挙から値を見る...

私の最初の考えは、許可を論理グループ(RuleGroupPermissionsRulePermissionsLocationPermissions、...)に分割し、クラス(WebAgentPermissions)各アクセス許可列挙型のプロパティを公開します。

パーミッションの値は反復しているように見えるので、おそらく最後に単一の列挙型で逃げることができます。

[Flags]
public enum Permissions
{
    View = 1,
    Add = 2,
    Edit = 4,
    Delete = 8
}

そして、WebAgentPermissionsクラスに、アクセス許可を設定する各エリアのプロパティを公開させます。

class WebAgentPermissions
{
    public Permissions RuleGroup { get; set; }
    public Permissions Rule{ get; set; }
    public Permissions Location{ get; set; }
    // and so on...
}
34
Fredrik Mörk

言語ドキュメンテーションは言う:

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個の値を許可します。しかし、それは確かに最大のようです。その後、リエンジニアリングを検討することになります。ソリューションの残りの部分についてあまり多くの知識がなければ、何が適しているかを正確に言うことはできません。ただし、特権識別子の配列(またはハッシュマップ)は、おそらく最も自然なアプローチです。

20
the.jxc

BitArray classを確認できます。多分あなたは将来それを使用するでしょう。

13
arbiter

C#では、列挙の一種であるがより柔軟な値を表現する1つの柔軟な方法は、次のように、事前に調理された値を使用できる静的クラスとして表現することです。

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
mqp

このアプリケーションを制御している場合、共通のアクセス許可セット(表示、追加、編集、削除、アップロード/インポート)とリソースセット(ユーザー、ロール、ルールなど)を思いつくでしょう。 Webページで、そのページに関連付けられているリソースタイプを見つけて、権限を確認します。おそらく次のようなもの:

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をユーザーに割り当てる)。問題をどれだけ知っているかに基づいて、どのようにそれを処理するかはわかりません。

4
Talljoe

あなたの質問への答えではなく、関連する提案:ビットシフトを使用して数値を指定します:

[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...

最初の10ではそれほど重要ではありませんが、その後は非常に便利になります。

1
DavidMoksha

私はこのような状況にはありませんでした。

ここに私が考えるものがあります、カテゴリごとに別々の列挙を作成し、それらをパラメータとして受け入れます。

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の仕組みを見てください。 OK、OKCancelは質問、情報、感嘆から分離されています。

1
shahkalpesh