开发者

Using enums in WCF Data Services

I'm trying to manual开发者_如何学编程ly build a WCF Data Service using a POCO data model and I cannot figure out how to properly expose enum values. Assuming a simple model like:

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

public enum OrderStatus
{
   New,
   InProcess,
   Complete
}

How do you expose the valuable information in the OrderStatus property via the OData WCF Data Service?

If you do nothing, the Data Service generates a runtime error (enum is invalid property). The only answer I've seen that at least resolves the error is to mark the enum property as Ignored, such as:

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

This works, but it forces you to "omit" valuable information from the service layer. Are there other options for working with enum values in WCF Data Services?

EDIT: Please notice this is WCF Data Services (aka Astoria). This is not raw WCF Services, in which case the answers are more clear.


Enums are currently not supported in WCF Data Services (the OData protocol doesn't support them either). The typical workaround is to use string and constant values, or integer and constant values.


Maybe we can "cheat" it with the below workaround:

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


As follow-up, the "wrapper" approach is ultimately what worked. Essentially, a small class is written to wrap the enum and return primitive int values in the Data Service:

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

This was largely based on the advice given for working around EF4's enum limits:

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

Hope this technique helps others that follow.


Assuming DataContract Serialization, like so:

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


You need to make the enum a Data Contract.

See here for an example: http://consultingblogs.emc.com/merrickchaffer/archive/2007/04/03/Passing-Enum-values-into-WCF-Service-operations.aspx

[Edit] Apparently, that's not always the case as seen here: Sharing Enum with WCF Service


You need to write own QueryPrivider

    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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜