比起純粹用數值,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。