在 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 错误:错误 5 自定义工具错误:无法为服务引用“MyService”生成代码