2010-08-25 38 views
17

Tôi đang cố gắng xây dựng một dịch vụ dữ liệu WCF theo cách thủ công bằng cách sử dụng mô hình dữ liệu POCO và tôi không thể tìm ra cách để hiển thị đúng giá trị enum. Giả sử một mô hình đơn giản như:Sử dụng enums trong WCF Dịch vụ dữ liệu

public class Order 
{ 
    public int ID {get; set;} 
    public string Description {get; set;} 
    public OrderStatus Status {get; set;} 
} 

public enum OrderStatus 
{ 
    New, 
    InProcess, 
    Complete 
} 

Làm thế nào để bạn tiếp xúc với những thông tin có giá trị trong OrderStatus bất động sản thông qua các dịch vụ dữ liệu OData WCF?

Nếu bạn không làm gì cả, Dịch vụ dữ liệu sẽ tạo ra lỗi thời gian chạy (enum là thuộc tính không hợp lệ). Câu trả lời duy nhất mà tôi đã nhìn thấy rằng ít nhất giải quyết các lỗi là để đánh dấu sự enum tài sản như Ignored, chẳng hạn như:

[System.Data.Services.IgnoreProperties("Status")] 
public class Order ... 

này hoạt động, nhưng nó buộc bạn phải "bỏ qua" thông tin giá trị từ lớp dịch vụ. Có các tùy chọn khác để làm việc với các giá trị enum trong WCF Data Services không?

CHỈNH SỬA: Vui lòng lưu ý đây là Dịch vụ dữ liệu WCF (aka Astoria). Đây không phải là Dịch vụ WCF thô, trong trường hợp đó các câu trả lời rõ ràng hơn.

+0

Đó là khuyến cáo để tránh sự đếm trong webservices vì ​​họ tạo ra vấn đề tương thích ngược tinh tế. Xem http://stackoverflow.com/a/788281/52277 –

Trả lời

16

Enums hiện không được hỗ trợ trong WCF Data Services (giao thức OData không hỗ trợ chúng). Cách giải quyết điển hình là sử dụng chuỗi và giá trị không đổi, hoặc giá trị nguyên và hằng số.

+0

Tôi sợ điều đó. Hạnh phúc để có xác nhận rõ ràng ít nhất. Tôi đang thử một số cách giải quyết "wrapper" vì vậy tôi không phải thực hiện những thay đổi lớn cho mô hình của mình chỉ để sử dụng Dịch vụ dữ liệu. Hy vọng rằng một trong những cách giải quyết sẽ hoạt động! – Todd

+1

@Vitek: Enums là một cấu trúc lập trình cực kỳ phổ biến, và đó là một bước kỳ lạ về phía sau để không sử dụng chúng. Có kế hoạch để bao gồm hỗ trợ enum trong các phiên bản tương lai của tiêu chuẩn OData, hoặc sẽ WCF dữ liệu dịch vụ cung cấp hỗ trợ tùy chọn khi cả hai đầu được biết là trên ngăn xếp MSFT? –

+0

Chúng tôi hiểu rằng enums là phổ biến, tiếc là họ không bao giờ gặp thanh tha cho đến nay. Họ khá cao trong danh sách những điều cần làm tiếp theo của chúng tôi. –

0

Bạn cần phải thực hiện enum một hợp đồng dữ liệu.

Xem ở đây cho một ví dụ: http://consultingblogs.emc.com/merrickchaffer/archive/2007/04/03/Passing-Enum-values-into-WCF-Service-operations.aspx

[Chỉnh sửa] Rõ ràng, đó không phải luôn luôn như vậy như đã thấy ở đây: Sharing Enum with WCF Service

+0

Cảm ơn bạn đã nhập liệu nhanh chóng, nhưng tôi nghĩ bạn đã bỏ lỡ rằng đây là WCF Data Services, không phải WCF đơn giản.Tôi đã thử các thuộc tính DataContract/EnumMember điển hình, nhưng chúng dường như không hoạt động với WCF Data Services (aka Astoria). – Todd

2

Giả sử DataContract serialization, như vậy:

[DataContract] 
public class Order 
{ 
    [DataMember] 
    public int ID {get; set;} 
    [DataMember] 
    public string Description {get; set;} 
    [DataMember] 
    public OrderStatus Status {get; set;} 
} 

[DataContract] 
public enum OrderStatus 
{ 
    [EnumMember] 
    New, 
    [EnumMember] 
    InProcess, 
    [EnumMember] 
    Complete 
} 
+0

Điều này thường hoạt động cho các dịch vụ WCF đơn giản, nhưng trong trường hợp này tôi hỏi về WCF Data Services (trước đây gọi là Astoria). Trong các thử nghiệm của tôi, giải pháp này KHÔNG làm việc để sử dụng enums trong Dịch vụ dữ liệu. Bạn đã thử nghiệm điều này với WCF Data Services chưa? – Todd

+0

Rất tiếc - apols. Có một hack bẩn trong các liên kết trên bài viết của Troy mà có thể làm việc cho bạn - thêm một int serializable thêm vào thực thể và sau đó cast enum để getter/setters (nhưng bỏ qua enum) – StuartLC

5

Có lẽ chúng ta có thể "ăn gian" nó bằng cách giải quyết dưới đây:

[System.Data.Services.IgnoreProperties("Status")] 
public class Order 
{ 
    public int ID {get; set;} 
    public string Description {get; set;} 
    public OrderStatus Status {get; set;} 
    public int StatusValue 
    { 
     get 
     { 
      return (int)this.Status; 
     } 
     set 
     { 
      // Add validation here 
      this.Status = (OrderStatus)value; 
     } 
    } 
} 

public enum OrderStatus 
{ 
    New, 
    InProcess, 
    Complete 
} 
+0

Rất gần giải pháp cuối cùng tôi đã sử dụng! – Todd

5

Như theo dõi, các "wrapper" cách tiếp cận là cuối cùng những gì làm việc. Về cơ bản, một lớp học nhỏ được ghi vào quấn enum và trở về nguyên thủy int giá trị trong các dịch vụ dữ liệu:

[IgnoreProperties("EnumValue")] 
public class OrderStatusWrapper 
{ 
    private OrderStatus _t; 

    public int Value 
    { 
     get{ return (int)_t; } 
     set { _t = (OrderStatus)value; } 
    } 

    public OrderStatus EnumValue 
    { 
     get { return _t; } 
     set { _t = value; } 
    } 

    public static implicit operator OrderStatusWrapper(OrderStatus r) 
    { 
     return new OrderStatusWrapper { EnumValue = r }; 
    } 

    public static implicit operator OrderStatus(OrderStatusWrapper rw) 
    { 
     if (rw == null) 
      return OrderStatus.Unresolved; 
     else 
      return rw.EnumValue; 
    } 
} 

này được chủ yếu dựa vào những lời khuyên đưa ra cho làm việc xung quanh enum giới hạn EF4 của:

http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx

Hy vọng kỹ thuật này sẽ giúp những người khác theo dõi.

+3

Thay thế _s bằng _t – Pakman

+0

Todd, tôi không thể tìm ra cách sử dụng trình bao bọc này ... bạn có thể xây dựng được không? –

0

Bạn cần phải viết QueryPrivider riêng

public object GetPropertyValue(object target, ResourceProperty resourceProperty) 
    { 
     object result = null; 
     PropertyInfo info = target.GetType().GetProperty(resourceProperty.Name); 
     if (info != null) 
      result = info.GetValue(target, null); 
     if (result is Enum) 
      return Convert.ToInt32(result); 
     return result; 
    } 


    public ResourceType GetResourceType(object target) 
    { 
     ResourceType result = null; 
     Type tp = target.GetType(); 
     if (tp.IsEnum) 
     { 
      result = ResourceType.GetPrimitiveResourceType(typeof(Int32)); 
      return result; 
     } 
     .... 
     return result; 
    } 
+0

Điều này thực sự cho một dịch vụ DATA wcf? Nếu có, bạn có thể cung cấp thêm chi tiết về cách thực hiện điều này không? – Jerther

Các vấn đề liên quan