在 WCF 数据服务中使用枚举

Posted

技术标签:

【中文标题】在 WCF 数据服务中使用枚举【英文标题】:Using enums in WCF Data Services 【发布时间】:2011-04-03 23:17:58 【问题描述】:

我正在尝试使用 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 数据服务(又名 Astoria)。这不是原始 WCF 服务,在这种情况下答案会更清楚。

【问题讨论】:

建议避免在 Web 服务中使用枚举,因为它们会产生微妙的向后兼容问题。见***.com/a/788281/52277 【参考方案1】:

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

【讨论】:

我害怕那个。很高兴至少有明确的确认。我正在尝试一些“包装器”解决方法,因此我不必为了使用数据服务而对我的模型进行大的更改。希望其中一种解决方法能够奏效! @Vitek:枚举是一种非常常见的编程结构,不使用它们是一种奇怪的倒退。是否有任何计划在 OData 标准的未来版本中包含枚举支持,或者当已知两端都在 MSFT 堆栈上时,WCF 数据服务是否会提供可选支持? 我们知道枚举很常见,但遗憾的是到目前为止它们从未遇到过。不过,它们在我们接下来要做的事情清单上相当靠前。 @Vitek:我发布了这个问题的更通用版本,并感谢您提供***.com/questions/3570249/… BTW 的任何见解,尽管有一些粗糙的边缘,我是 MSFT 工作的忠实粉丝在这方面做。 您评论中的链接指向了这个问题,您能重新发布正确的吗? :-)【参考方案2】:

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

[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

【讨论】:

非常接近我使用的最终解决方案!【参考方案3】:

作为后续,“包装器”方法最终奏效了。本质上,编写了一个小类来包装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 限制提供的建议:

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

希望这项技术可以帮助其他人。

【讨论】:

托德,我不知道如何使用这个包装器......你能详细说明一下吗?【参考方案4】:

假设 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 服务,但在这种情况下,我询问的是 WCF 数据服务(以前称为 Astoria)。在我的测试中,此解决方案不适用于在数据服务中使用枚举。您是否使用 WCF 数据服务对此进行了测试? 哎呀 - apols。 Troy 帖子上的链接中有一个肮脏的 hack,它可能对您有用 - 向实体添加一个额外的可序列化 int,然后将枚举转换为 getter / setter(但忽略枚举)【参考方案5】:

您需要使枚举成为数据协定。

查看示例:http://consultingblogs.emc.com/merrickchaffer/archive/2007/04/03/Passing-Enum-values-into-WCF-Service-operations.aspx

[编辑] 显然,情况并非总是如此: Sharing Enum with WCF Service

【讨论】:

感谢您的快速输入,但我认为您错过了这是 WCF 数据服务,而不是普通的 WCF。我已经尝试过典型的 DataContract/EnumMember 属性,但它们似乎不适用于 WCF 数据服务(又名 Astoria)。【参考方案6】:

你需要编写自己的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 DATA 服务吗?如果是这样,您能否详细说明如何做到这一点?

以上是关于在 WCF 数据服务中使用枚举的主要内容,如果未能解决你的问题,请参考以下文章

您是不是在 WCF Web 服务中使用枚举类型?

WCF 数据服务 + 带有枚举的实体

WCF 确保存在必要的枚举值

将标志添加到枚举后:Wcf 错误:错误 5 自定义工具错误:无法为服务引用“MyService”生成代码

将单个枚举值传递给 WCF 服务时,protobuf-net 引发有关无效线路类型的异常

按照Web Service方式调用WCF服务的问题