HasFlag无法识别角色分配

时间:2011-01-17 20:29:52

标签: c# .net authorization bit-manipulation

我正在使用[Flags]修饰的Enum来控制我的MVC2应用程序中的自动化。以下是我的代码示例:

[Flags]
public enum SecurityRoles
{
    None = 0,
    Executive = 1,
    BackOffice = 2,
    AccountManager = 4,
    Consultant = 8,
    Administrator = 16
}

[TestMethod]
public void MultipleSelectionsTest()
{
    var requiredRoles = SecurityRoles.Executive | SecurityRoles.BackOffice;
    var user1Roles = SecurityRoles.Executive | SecurityRoles.Administrator | SecurityRoles.BackOffice | SecurityRoles.Consultant;
    var user1HasAccess = user1Roles.HasFlag(requiredRoles);

    var user2Roles = SecurityRoles.Administrator | SecurityRoles.BackOffice | SecurityRoles.Consultant;
    var user2HasAccess = user2Roles.HasFlag(requiredRoles);


    Assert.IsTrue(user1HasAccess);  //returns true
    Assert.IsTrue(user2HasAccess);  //returns false
}

如您所见,user2Roles包含BackOffice角色,requiredRoles也包含BackOffice角色,但user2HasAccess为false。这是为什么?我错过了什么? user1HasAccess为true。

2 个答案:

答案 0 :(得分:3)

如果我错了(因为我可能),请纠正我,但是当你执行Enum标志检查时,.NET基本上对表示标志总和的整数进行二进制算术。

因此SecurityRoles.Administrator | SecurityRoles.BackOffice | SecurityRoles.Consultant与二进制值的值为26或11010相同。

当你调用Enum.HasFlags时,正在执行的操作是return thisInstance & flag == flag

因此,如果您在二进制文件中检查前面提到的标记集(SecurityRoles.Executive | SecurityRoles.BackOffice的值为3或11,则数学运算如下:

11010 - 26 Administrator | BackOffice | Consultant
00011 -  3 Executive | BackOffice
----- 
00010 -  2 BackOffice which really doesn't mean anything useful

然后就会发现26 & 3 == 3是假的。

为了彻底,给定SecurityRoles.Executive | SecurityRoles.Administrator | SecurityRoles.BackOffice | SecurityRoles.Consultant值为27或11011二进制,数学运算如下:

11011 - 26 Executive  | Administrator | BackOffice | Consultant
00011 -  3 Executive | BackOffice
----- 
00011 -  3 Executive | BackOffice

然后就会发现26 & 3 == 3是真的。

像这样的扩展方法可能是值得的(未经测试)

public static bool HasFlags(this Enum source, Enum[] flags) 
{
    return flags.Any(f => source.HasFlag(f));
}

答案 1 :(得分:0)

感谢您的帮助Wes P.我能够接受您的建议,并将其与此处的扩展程序相结合:link text并提出了我自己的扩展来解决问题

这是我的扩展。它使用我在上面链接中找到的扩展方法中的GetFlags()方法。

public static bool HasFlags(this Enum userRoles, Enum requiredRoles)
        {
            var hasFlags = false;
            var userRolesList = userRoles.GetFlags();
            var requiredRolesList = requiredRoles.GetFlags();

            foreach (var role in userRolesList)
            {
                var role1 = role;
                hasFlags = requiredRolesList.Any(securityRole => role1.CompareTo(securityRole) == 0);

                if(hasFlags)
                    break;
            }

            return hasFlags;
        }