在前一篇如何使用中文列舉(Enum)?, 介紹了如何取得列舉中文說明的方法, 但每當有新的列舉時都要再寫一次嗎?
當然不, 此篇將會研究如何抽成共用的方法.
我們都知道, 相同的程式碼要抽成共用的方法來呼叫, 維護上比較便利, 程式碼也比較簡潔.
但有些情況無法去判斷是否有共用的程式碼時該怎麼辦?
小魯這邊的做法是當相近或是相同的程式碼些第二次的時候, 就要有警覺性.
當第三次發生時就一定要寫成共用方法, 甚至大部分在第二次就抽成共用了.
取得Enum的中文描述的方法很明顯不會是僅限於某個Enum使用,
所以應該要抽成共用方法來使用.
在目前泛型正夯的時期, 小魯也不免俗的來試一下
修改後的泛型方法如下:
public static class EnumHelper
{
public static string GetDescription<T>(string value)
{
Type type = typeof(T);
var name = Enum.GetNames(type)
.Where(f => f.Equals(value, StringComparison.CurrentCultureIgnoreCase))
.Select(d => d)
.FirstOrDefault();
//// 找無相對應的列舉
if (name == null)
return string.Empty;
//// 利用反射找出相對應的欄位, 並取得欄位設定DescriptionAttribute的值
var field = type.GetField(name);
var customAttribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
//// 無設定Description Attribute, 回傳Enum欄位名稱
if (customAttribute == null || customAttribute.Length == 0)
return name;
//// 回傳Description Attribute的設定
return ((DescriptionAttribute)customAttribute[0]).Description;
}
}
小魯寫一個EnumHelp的靜態類別, 將取得中文描述方法寫成一個靜態的泛型方法
外部在呼叫時再將列舉帶入T中
static void Main(string[] args)
{
var bookType = EnumHelper.GetDescription<BookTypeEnum>(BookTypeEnum.ComicBook.ToString());
var result = string.Format("BookTypeEnum Description: {0}", bookType);
Console.Write(result);
Console.Read();
}
如此一來, 就可達到共用的效果.
.
.
.
有些眼尖的網友一定會發現一個問題
路人甲: "疑~小魯你這寫法任一型別都可以帶入且編譯不會報錯"
小魯: "安啦~等測試的時候就知道你寫錯了, 到時候再改就好啦!!"
路人乙: "小魯你太不負責任了啦~(╯-_-)╯ ~╩╩ (怒翻桌)"
為了避免網友翻桌, 小魯只好再找解決方案
有些人這時候一定會想到替泛型T加上條件約束不就好了
當初我也是這麼想
但查詢的結果發現沒有對Enum的條件約束
甚至在MSDN 限制適用於列舉型別中有提到一句話
"列舉型別不能是泛型,除非是巢狀於泛型型別中,才能是泛型。換句話說,列舉型別不能有自己的型別參數。"
真是晴天霹靂~
(註: 如果有網友知道Enum的條件約束, 麻煩請不吝告知, 謝謝!!)
但是沒關係, 山不轉路轉
換個方式來解
這時候可以回歸到用物件的多型來處理
public static class EnumHelper
{
public static string GetDescription(Enum value)
{
Type type = value.GetType();
//// 利用反射找出相對應的欄位
var field = type.GetField(value.ToString());
//// 取得欄位設定DescriptionAttribute的值
var customAttribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
//// 無設定Description Attribute, 回傳Enum欄位名稱
if (customAttribute == null || customAttribute.Length == 0)
{
return value.ToString();
}
//// 回傳Description Attribute的設定
return ((DescriptionAttribute)customAttribute[0]).Description;
}
}
參數型別直接用Enum,
利用型別的逆變性, 來限定參數只能是列舉型別
static void Main(string[] args)
{
var bookType = EnumHelper.GetDescription(BookTypeEnum.ComicBook);
var result = string.Format("BookTypeEnum Description: {0}", bookType);
Console.Write(result);
Console.Read();
}
如此一來, 就可以僅限制列舉型別又可達到共用的方法
另外, 此方法還可改寫成擴充方法來處理, 呼叫時更為便利
擴充方法這裡就不另外贅述了, 有興趣的網友可以去google看看
網路上有很多文章
參考網站:
https://msdn.microsoft.com/zh-tw/library/6e3t9w21%28v=vs.90%29.aspx
註: 此篇文章有觀念錯誤之處,歡迎各位大大不吝指教
