利用Generic解決Web Service 中 Enum的向下相容問題

比起純粹用數值,Enum的優點之一是在寫程式的時候可以清楚的知道所有支援的列舉值。

在Client-Server架構下,使用Enum需要注意向下相容的問題。

適合在Web Service中使用Enum的 Best practice有:

  • Enum data type永遠都是從client傳給server,不會由server傳給client的狀況。
  • Sealed Enum,Enum的值不會再新增或改變。

如果不是上述狀況,當server新增的Enum的值,client application的Enum定義值沒有同步更新的話,當server傳遞新的Enum值給client的時候,client application會因為沒有這個新的Enum定義值,而發生system error。

對於稍具規模的client\server架構,Server可能同時serve多種類型,或為數眾多的client systems。新增的Enum值可能造成跨系統間很大的問題。

目前還沒有聽說ASP.NET對Enum的向下相容性有比較好的solution。

我最近遭遇這個問題,辦法是利用Generic來解決這個問題。


// Server side


public struct ServerEnum
{
public ServerEnum(T value)  : this()
{
Value = value;
}


public T Value {get; set;}

[DataMember]
internal string Name {get; set;}
public static implicit operator ServerEnum(T value)
{
return new ServerEnum(value);
}

public static implicit operator T(ServerEnum value)
{
return value.Value;
}

[OnSerializing]
internal void OnSerializing(StreamingContext context)
{
Name = Value.ToString();
}

[OnDeserialized]
internal void OnDeserialized(StreamingContext context)
{

if ((!string.IsNullOrEmpty(Name)) && (Enum.IsDefined(typeof(T), Name)))
{
Value = (T)Enum.Parse(typeof(T), Name);
}
else
{
Value = default(T);
}
}

}

// Server object

public class Cloth
{
public System.Int32 ID    { get; set;  }
public ServerEnum size { get; set;  }
}

// Real Enum "Size"
public enum Size
{
M = 0,
S = -1,
L = 1,
XL = 2
}

// Client code
...
Cloth cloth= new Cloth();
cloth.size = Size.XL;

Server.RefundCloth(newCloth);

...

Client 依然可以直接操作Size這個Enum。

當server新定義了新的Size XXL,client deserialize的時候會把找不到定義的Enum設為Default值。避免Deserialize error。

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s