Использование перечислений в службах передачи данных WCF
Я пытаюсь вручную создать службу данных WCF с использованием модели данных POCO, и я не могу понять, как правильно выставлять значения 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
}
Как вы можете предоставить ценную информацию в свойстве OrderStatus
через службу данных OData WCF?
Если вы ничего не делаете, Служба данных генерирует ошибку времени выполнения (enum is invalid property). Единственный ответ, который я видел, по крайней мере, разрешает ошибку - отметить свойство enum
как игнорируемое, например:
[System.Data.Services.IgnoreProperties("Status")]
public class Order ...
Это работает, но это заставляет вас "опускать" ценную информацию с уровня сервиса.
Существуют ли другие варианты работы с значениями перечисления в службах данных WCF?
РЕДАКТИРОВАТЬ: Обратите внимание, что это службы передачи данных WCF (aka Astoria). Это не сырые службы WCF, и в этом случае ответы более ясны.
Ответы
Ответ 1
В настоящее время обновления в службах передачи данных WCF не поддерживаются (протокол OData также не поддерживает их).
Типичным обходным решением является использование строковых и постоянных значений, или целочисленных и постоянных значений.
Ответ 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
и return primitive 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 Serialization, например:
[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
}
Ответ 5
Вам нужно сделать перечисление Контрактом данных.
См. здесь пример: http://consultingblogs.emc.com/merrickchaffer/archive/2007/04/03/Passing-Enum-values-into-WCF-Service-operations.aspx
[Edit] По-видимому, это не всегда так, как показано здесь:
Совместное использование с помощью службы WCF
Ответ 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;
}