2011-01-17 2 views
2

Я использую Enum, украшенную [Flags] для управления автозагрузкой в ​​моем приложении MVC2. Ниже мои примеры кода:HasFlag не распознает назначение роли

[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 containes BackOffice роль и requiredRoles также содержит BackOffice роль, однако, user2HasAccess ложно. Почему это? Что мне не хватает? user1HasAccess - это правда.

ответ

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)); 
} 
+0

Ваш метод расширение может быть улучшено, это решение, вероятно, быстрее: открытая статическая BOOL HasAnyFlag (этот источник Enum, Enum флаги) {возвращение (источник и флаги) = 0; }. Также непроверенный btw – JBSnorro

+0

@JBSnorro ваш код не работает, содержит ошибку сравнения. – Tomas

+1

@ Томас. Sry, это, очевидно, должно было быть public public bool HasAnyFlag (этот источник Enum, флаги Enum) {return (Convert.ToInt32 (source) & Convert.ToInt32 (flags))! = 0; } ' – JBSnorro

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; 
     } 
Смежные вопросы