HasFlag не распознает назначение роли
Я использую Enum, украшенный [Flags] для управления автоматизацией в моем приложении 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 - это правда.
2 ответа
Поправьте меня, если я ошибаюсь (потому что мог бы быть), но когда вы выполняете проверки флагов 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));
}
Спасибо за вашу помощь Уэс П. Я смог принять ваше предложение и объединить его с найденным здесь расширением: текст ссылки и придумал собственное расширение для решения проблемы.
Вот мое расширение. Он использует метод 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;
}