2009-02-03 9 views
6

Tôi có một liệt kê thuộc tính cờ đó là đằng sau một dịch vụ web như sau:Flags với các dịch vụ web

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

Vấn đề của tôi là người tiêu dùng dịch vụ web của tôi không có giá trị không đổi ban đầu của enum. Kết quả là bên lớp proxy client có cái gì mà số tiền này:

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

Và như vậy, khi người tiêu dùng đang kiểm tra cho "Đọc" truy cập này sẽ là sai lầm ngay cả khi "testItem" là "đầy đủ"

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

Tôi làm cách nào để cung cấp cờ hiệu quả cho dịch vụ web?

EDIT:

Theo this Điều đó có thể không thể làm những gì tôi đang tìm kiếm để làm. Ivan Krivyakov khẳng định

Imperfect Tính minh bạch của Enums

Nó chỉ ra rằng sự đếm không phải là minh bạch như chúng tôi muốn họ được. Có ba vấn đề dính:

  1. Nếu mã server-side tuyên bố một enum và gán số cụ thể giá trị cho các thành viên, các giá trị sẽ không được hiển thị cho khách hàng.
  2. Nếu mã phía máy chủ khai báo [Flags] enum với mặt nạ "hợp chất" giá trị (như màu trắng = đỏ | Xanh | Xanh), nó không được phản ánh đúng trên mặt của máy khách .
  3. Nếu máy chủ hoặc ứng dụng khách truyền một giá trị "bất hợp pháp" nằm ngoài phạm vi phạm vi của enum, nó gây ra một ngoại lệ trong bộ tách XML trên phía bên kia.

Vì vậy, tôi tự hỏi nếu đây chỉ là một hạn chế và không thể.

Trả lời

3

Tôi đã thực hiện nghiên cứu sâu rộng về điều này và thấy rằng không thể tuần tự hóa các hằng số liệt kê thông qua dịch vụ web. Lưu ý rằng để hoàn thành mục tiêu của bạn, bạn không cần liệt kê Không có hoặc Toàn bộ. Hai liệt kê này có thể được ngụ ý với sự kết hợp đọc/ghi:

Bạn có thể truy cập đầy đủ nếu AccessLevels = Đọc | Viết và none nếu AccessLevels của bạn = 0 [gì]

enumerations của bạn sẽ trông như thế này:

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

Tôi nghĩ rằng đây là con đường mà tôi có thể cần phải thực hiện ở đây. Tôi thực sự muốn có thể có tùy chọn "Không" được viết cho người dùng của tôi. – Brawndo

0

Tôi đã gặp sự cố tương tự và đã làm tròn nó bằng cách thêm một dịch vụ web khác để trả lại giá trị cờ currect trước.

Sau đó, những giá trị đó trở thành giá trị tôi đã sử dụng trong so sánh.

Có thể không phải là giải pháp sạch nhất nhưng hoạt động.

Chỉnh sửa:

Câu trả lời ban đầu của tôi cho rằng giá trị được chuyển qua dưới dạng dịch vụ web riêng biệt thay vì trong một môi trường.

Tuy nhiên, xung quanh, có vẻ như một liệt kê 0,1,2 được ánh xạ tới 1,2,4 trên một dịch vụ web (ngay cả khi thuộc tính [Flags] được đặt) là một vấn đề phổ biến.

Giải pháp được đề xuất bởi một số người là sửa đổi định nghĩa điều tra ban đầu và bắt đầu từ 1 thay vì 0.

+0

bạn có thể xây dựng một chút? – Brawndo

0

Cờ phải là bội số của hai và trong trường hợp của bạn, cờ của bạn là (0,1,2,3). Thử thay đổi định nghĩa của cấu trúc thành:

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

Và xem nó có hoạt động tốt hơn không.

(Tôi hy vọng Im không làm một kẻ ngốc của bản thân mình, muộn và Im của nó trên đường đến chiếc giường ..)

+0

Điều đó vẫn không hoạt động. Tôi đã nhìn thấy vấn đề này trước đây. Với sự đánh số bạn đề cập đến người tiêu dùng của bạn vẫn sẽ thấy như sau: AccessLevels enum công { None = 1, đọc = 2, Write = 4, Full = 8, } – Rorzilla

+0

@Rorzilla có mà thực sự là trường hợp vẫn còn. @Stefan Tôi có thể "sửa" bằng cách xóa "Đầy đủ" và "Không" thì lớp proxy sẽ trở thành Đọc = 1 và Viết = 2 nhưng tôi vẫn muốn cung cấp cho người dùng tùy chọn không có để họ không phải "chỉ biết" điều gì đó và không phải sử dụng giá trị 0 – Brawndo

+1

@Stefan - Không, cờ phải là các bit riêng lẻ, trong đó 1 là giá trị đầu tiên. Không nên * luôn luôn * được định nghĩa là 0 vì điều đó có nghĩa là không có bit nào được đặt. Nếu None = 1 thì 0 là gì? Thật không? –

0

Một lựa chọn sẽ được cung cấp một lớp tiết hơn thay vì enum ví dụ

[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; 
    } 
} 
} 

Tùy chọn khác mà tôi có thể thấy là cung cấp phương pháp theo ngôn ngữ mà họ đang sử dụng để kết nối thành công số nguyên bạn đang gửi. Nhà điều hành cờ có nghĩa là C# không chút che để tìm thấy nếu một lá cờ cá nhân được đánh dấu

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

như vậy để kiểm tra xem có bất kỳ sự cho phép, bạn nên xem nếu bit được thiết lập


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. 
} 

Xin lưu ý giải pháp thứ hai này là mong manh hơn, nếu bạn thay đổi định nghĩa của accessLevels, khách hàng của bạn sẽ âm thầm bỏ lỡ hành vi.