Использование перечислений в службах данных WCF - PullRequest
17 голосов
/ 26 августа 2010

Я пытаюсь вручную создать службу данных 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 является недействительным свойством). Единственный ответ, который я видел, по крайней мере, устраняющий ошибку, - пометить свойство enum как игнорируемое, например:

[System.Data.Services.IgnoreProperties("Status")]
public class Order ...

Это работает, но заставляет вас "опускать" ценную информацию из сервисного уровня. Существуют ли другие варианты работы со значениями перечисления в службах данных WCF?

РЕДАКТИРОВАТЬ: Обратите внимание, это Службы данных WCF (он же Astoria). Это не необработанные сервисы WCF, в этом случае ответы более ясны.

Ответы [ 6 ]

16 голосов
/ 26 августа 2010

Перечисления в настоящее время не поддерживаются в службах данных WCF (протокол OData их также не поддерживает).Типичный обходной путь - использование строковых и постоянных значений или целых и постоянных значений.

5 голосов
/ 28 августа 2010

В качестве последующего подхода подход «обертка» в конечном итоге сработал. По сути, небольшой класс написан для переноса значений 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;
    }
}  

Это в значительной степени основывалось на рекомендациях по обходу ограничений enum EF4:

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

Надеюсь, что эта техника поможет другим, которые следуют.

5 голосов
/ 26 августа 2010

Может быть, мы можем «обмануть» его с помощью нижеприведенного решения:

[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
}
2 голосов
/ 26 августа 2010

Предполагая сериализацию 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
}
0 голосов
/ 09 декабря 2011

Вам нужно написать собственный 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;
    }
0 голосов
/ 26 августа 2010

Вам необходимо заключить договор на передачу данных.

См. Здесь пример: http://consultingblogs.emc.com/merrickchaffer/archive/2007/04/03/Passing-Enum-values-into-WCF-Service-operations.aspx

[Edit] Очевидно, это не всегда так, как показано здесь: Совместное использование Enum с сервисом WCF

...