Подтвердить что ты не робот

Использование перечислений в службах передачи данных 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, и в этом случае ответы более ясны.

4b9b3361

Ответ 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
}

Ответ 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;
    }