问题
I'm using an Enum decorated with [Flags] to control autoization within my MVC2 app. Below is my code examples:
[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
}
As you can see, user2Roles containes BackOffice role and requiredRoles also contains BackOffice role, however, user2HasAccess is false. Why is that? What am I missing? user1HasAccess is true.
回答1:
Correct me if I'm wrong (because I could be), but when you perform Enum flag checks, .NET is essentially doing binary arithmetic on an integer which represents the sum of the flags.
So having SecurityRoles.Administrator | SecurityRoles.BackOffice | SecurityRoles.Consultant is the same as having a value of 26 or 11010 in binary.
When you make the call to Enum.HasFlags, the operation that's being performed is return thisInstance & flag == flag
So if you're checking the previously mentioned flag set against your required roles of SecurityRoles.Executive | SecurityRoles.BackOffice a value of 3 or 11 in binary, the math goes something like this:
11010 - 26 Administrator | BackOffice | Consultant
00011 - 3 Executive | BackOffice
-----
00010 - 2 BackOffice which really doesn't mean anything useful
Then it would follow that 26 & 3 == 3 is false.
And for the sake of being thorough, given SecurityRoles.Executive | SecurityRoles.Administrator | SecurityRoles.BackOffice | SecurityRoles.Consultant a value of 27 or 11011 in binary, the math goes like this:
11011 - 26 Executive | Administrator | BackOffice | Consultant
00011 - 3 Executive | BackOffice
-----
00011 - 3 Executive | BackOffice
Then it would follow that 26 & 3 == 3 is true.
An extension method something like this, might be worthwhile (untested)
public static bool HasFlags(this Enum source, Enum[] flags)
{
return flags.Any(f => source.HasFlag(f));
}
回答2:
Thanks for your help Wes P. I was able to take your suggestion and combine it with the extension found here: link text and came up with my own extension to solve the problem
Here's me extension. It uses the GetFlags() method found in the extension methods i found in the link above.
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;
}
来源:https://stackoverflow.com/questions/4717550/hasflag-not-recognizing-role-assignment