Флаги с веб-сервисами - PullRequest
       31

Флаги с веб-сервисами

6 голосов
/ 03 февраля 2009

У меня есть перечисление атрибута флага, стоящее за веб-службой следующим образом:

[Serializable,Flags]
public enum AccessLevels
{
    None = 0,
    Read = 1,
    Write = 2,
    Full = Read | Write
}

Моя проблема в том, что потребитель моего веб-сервиса не имеет исходных постоянных значений перечисления. Результирующая сторона клиента прокси-класса имеет что-то такое:

{
   None = 1,
   Read = 2,
   Write = 4,
   Full = 8
}

И поэтому, когда потребитель проверяет доступ «Чтение», это будет ложным, даже если «testItem» имеет значение «Полный»

((testItem & Svc.Read) == Svc.Read)

Как правильно предоставить флаги через веб-сервис?

EDIT:

Согласно этой статье , возможно, не удастся сделать то, что я хочу сделать. Иван Кривяков заявляет

несовершенная прозрачность перечислений

Оказывается, что перечисления не так прозрачный, как мы хотели бы, чтобы они были. Есть три проблемы:

  1. Если код на стороне сервера объявляет перечисление и назначает определенный числовой ценности для своих членов, эти ценности не будет виден клиенту.
  2. Если код на стороне сервера объявляет перечисление [Flags] с «составной» маской значения (как в White = Red | Green | Blue), это не отражается должным образом на клиентская сторона.
  3. Если сервер или клиент передает «недопустимое» значение, которое находится за пределами объем перечисления, это вызывает исключение в XML-десериализаторе на другая сторона.

Так что мне интересно, если это просто ограничение и невозможно.

Ответы [ 4 ]

3 голосов
/ 04 февраля 2009

Я провел обширное исследование по этому вопросу и обнаружил, что невозможно сериализовать константы перечисления через веб-сервис. Обратите внимание, что для достижения вашей цели вам не нужны перечисления None или Full. Эти два перечисления могут подразумеваться с помощью комбинации чтения / записи:

Вы можете получить полный доступ, если ваш AccessLevels = Read | Написать и нет, если ваш AccessLevels = 0 [ничего]

Ваши перечисления будут выглядеть так:

[Serializable,Flags]
public enum AccessLevels
{
    Read = 1,
    Write = 2
}
0 голосов
/ 03 февраля 2009

Флаги должны быть кратны двум, и в вашем случае ваши флаги равны (0,1,2,3). Попробуйте изменить определение структуры на:

[Serializable,Flags]
public enum AccessLevels{    
None = 1,    
Read = 2,    
Write = 4,    
Full = Read | Write}

И посмотри, работает ли он лучше.

(Надеюсь, я не обманываю себя, уже поздно, и я иду к кровати ..)

0 голосов
/ 03 февраля 2009

Один из вариантов - предоставить более подробный класс вместо перечисления, например,

[Serializable]
public class AccessPermission{
 public boolean None{get;set;}
 public boolean Read{get;set;}
 public boolean Write{get;set;}
 public boolean Full{get;set;}

 public AccessPermission(AccessLevels level){
  None = false;
  Read = false;
  Write = false;
  Full = false;

  switch(level){
  case AccessLevels.None:
   break;
  case AccessLevels.Read:
   Read = true;
   break;
  case AccessLevels.Write:
   Write = true;
   break;
  case AccessLevels.Full:
   Read = true;
   Write = true;
   Full = true;
   break;
  }
 }
} 

Другой вариант, который я вижу, - это предоставление метода на любом языке, который они используют для успешного взаимодействия с целым числом, которое вы отправляете. Оператор флага означает, что c # выполняет битовую маскировку, чтобы определить, помечен ли отдельный флаг

0001 -> None
0010 -> Read
0100 -> Write
0110 -> Full

поэтому для проверки любого разрешения вы должны увидеть, установлен ли этот бит


public static boolean CanRead(int accessLevel){
 return (accessLevel | 2) > 0 // return true if read bit set, using bitwise or
}

public static boolean CanWrite(int accessLevel){
 return (accessLevel | 4) > 0 // return true of write bit set.
}

Обратите внимание, что это второе решение более хрупкое, если вы измените определение accessLevels, ваш клиент будет молча пропускать поведение.

0 голосов
/ 03 февраля 2009

У меня была похожая проблема, и я обошел ее, добавив еще один веб-сервис, который сначала возвращает значения флага currect.

Затем они стали значениями, которые я использовал в сравнении.

Возможно, это не самое чистое решение, но оно работает.

Edit:

Мой оригинальный ответ предполагал, что значения передаются как отдельный веб-сервис, а не как перечисление.

Тем не менее, возни, кажется, что перечисление 0,1,2, сопоставляемое с 1,2,4 через веб-сервис (даже если атрибут [Flags] установлен) является распространенной проблемой.

Решение, предложенное несколькими людьми, состоит в том, чтобы изменить исходное определение перечисления и начать с 1, а не с 0.

...