C# 在WCF数据服务中使用枚举

C# 在WCF数据服务中使用枚举,c#,wcf,enums,wcf-data-services,odata,C#,Wcf,Enums,Wcf Data Services,Odata,我试图使用POCO数据模型手动构建WCF数据服务,但我不知道如何正确地公开enum值。假设一个简单的模型,如: public class Order { public int ID {get; set;} public string Description {get; set;} public OrderStatus Status {get; set;} } public enum OrderStatus { New, InProcess, Complete

我试图使用POCO数据模型手动构建WCF数据服务,但我不知道如何正确地公开
enum
值。假设一个简单的模型,如:

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

public enum OrderStatus
{
   New,
   InProcess,
   Complete
}
如何通过OData WCF数据服务公开
OrderStatus
属性中的有价值信息?

如果不执行任何操作,数据服务将生成运行时错误(枚举是无效属性)。我看到的唯一解决此错误的方法是将
enum
属性标记为已忽略,例如:

[System.Data.Services.IgnoreProperties("Status")]
public class Order ...
这是可行的,但它会迫使您从服务层“忽略”有价值的信息。 在WCF数据服务中使用枚举值是否还有其他选项


编辑:请注意这是WCF数据服务(又名Astoria)。这不是原始的WCF服务,在这种情况下答案更清楚。

您需要将枚举设置为数据契约

有关示例,请参见此处:

[编辑]显然,情况并非如此:
假设DataContract序列化,如下所示:

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

WCF数据服务当前不支持枚举(OData协议也不支持它们)。 典型的解决方法是使用字符串和常量值,或整数和常量值。

也许我们可以使用以下解决方法“欺骗”它:

[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
}
作为后续行动,“包装器”方法最终起作用。本质上,编写一个小类来包装
enum
,并在数据服务中返回原语
int
值:

[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;
    }
}  
这主要是基于针对EF4的
enum
限制给出的建议:


希望这项技术能帮助其他人跟进。

您需要编写自己的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;
    }

这通常适用于普通的WCF服务,但在本例中,我询问的是WCF数据服务(以前称为Astoria)。在我的测试中,此解决方案不适用于在数据服务中使用枚举。你用WCF数据服务测试过这个吗。Troy文章中的链接中有一个肮脏的漏洞,可能对您有用-向实体添加一个额外的可序列化int,然后将枚举强制转换为getter/setter(但忽略枚举),感谢您的快速输入,但我认为您没有注意到这是WCF数据服务,而不是普通的WCF。我尝试过典型的DataContract/EnumMember属性,但它们似乎不适用于WCF数据服务(又名Astoria)。很高兴至少有明确的确认。我正在尝试一些“包装器”解决方法,这样我就不必为了使用数据服务而对模型进行重大更改。希望其中一个变通办法能奏效@Vitek:Enum是一种非常常见的编程结构,不使用它们是一种奇怪的倒退。是否有计划在OData标准的未来版本中包含枚举支持,或者当已知两端都在MSFT堆栈上时,WCF数据服务是否会提供可选支持?我们知道枚举是常见的,不幸的是,它们到目前为止从未达到这一标准。不过,它们在我们下一步要做的事情列表中占据相当高的位置。@Vitek:我发布了这个问题的一个更一般的版本,并希望您能提供任何见解。顺便说一句,尽管有一些粗糙的边缘,我是MSFT在这一领域所做工作的忠实粉丝。您评论中的链接指向这个问题,请转寄下一张好吗?:-)非常接近我使用的最终解决方案!建议避免Web服务中的枚举,因为它们会产生微妙的向后兼容问题。看Todd,我不知道如何使用这个包装器。。。你能详细说明一下吗?这真的是针对wcf数据服务的吗?如果是这样的话,你能提供更多关于如何实现这一点的细节吗?