CODE-Convert Enum+DescriptionAttribute to ListItems
3 | 8,953 |
[Abstract] Here is a sample to store text descriptions of enum fields to DescriptionAttribute, and convert them to a enum field name to description dictionary. So we can use it as the data source of dropdownlist or listbox easily.
開發系統時,常會用到下拉選單選項文字與值不同的設計。一般而言,文字要明確完整方便User閱讀,而各文字對應值常需配合資料庫欄位寬度,寫入資料庫時得轉成兩、三碼固定長度的特定代碼。
如下例,資料庫欄位為VARCHAR(2),四個選項各有其對應的兩碼代碼。
要處理上述選項文字與值不同的狀況,使用config檔、資料檔或資料庫保存對應表是一種解決方式,另一種做法是將它宣告成enum,如此在Visual Studio中可以享受Intellisense提示,甚至可用Code Snippet自動產生所有switch..case,最重要的,若打錯字也可在編譯期間被發現。
在之前討論enum, string, int轉換的文章裡,網友大估分享了用[Description("...")]保存列舉描述的做法,不失為一個簡潔的對應文字保存方式,例如:
排版顯示純文字
public enum ViewEngineType
{
[Description("Razor")]
RZ,
[Description("Webform(ASCX)")]
WF,
[Description("Spark")]
SP,
[Description("NHaml")]
NH
}
最近遇到類似需求,決定一不做二不休,寫了一個小函數將以上的列舉宣告直接轉成DropDownList可用的資料來源。廢話不多說,直接看Code:
排版顯示純文字
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
public partial class EnumDropdown_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DropDownList1.DataSource =
EnumListHelper.GetEnumDescDictionary(typeof(ViewEngineType));
DropDownList1.DataTextField = "value";
DropDownList1.DataValueField = "key";
DropDownList1.DataBind();
}
}
}
public enum ViewEngineType
{
[Description("Razor")]
RZ,
[Description("Webform(ASCX)")]
WF,
[Description("Spark")]
SP,
[Description("NHaml")]
NH
}
public static class EnumListHelper
{
//enum在執行階段是不會變動的,故使用Cache避免反覆執行
static Dictionary<Type, Dictionary<string, string>> _cache
= new Dictionary<Type, Dictionary<string, string>>();
//將enum的列舉文字及[Description("..")]轉成Dictionary<string, string>
public static Dictionary<string, string> GetEnumDescDictionary(Type enumType)
{
if (_cache.ContainsKey(enumType))
return _cache[enumType];
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (string name in Enum.GetNames(enumType))
{
FieldInfo fi = enumType.GetField(name);
DescriptionAttribute[] attrs =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
dict.Add(name, attrs.Length > 0 ? attrs[0].Description : name);
}
_cache.Add(enumType, dict);
return dict;
}
}
Comments
# by 大估
關於Enum+DescriptionAttribute,在.net3.5還有另一種寫法,提供給大家作參考… http://www.codeproject.com/KB/cs/enumdatabinding.aspx?select=2217063
# by 小黑
請問黑大,因為一般大都是將資料鍵在資料庫,哪些狀況下可以考慮使用 enum 當作資料來源?
# by Jeffrey
to 小黑, 這問題倒沒有絕對答案。列舉項目清單保存在DB的好處是未來要新增項目時不需修改程式、且可以在Procedure端JOIN出相關代碼的對照中文,但缺點是會增加系統複雜度(要多寫讀取DB的部分、維護列舉項目的UI)、耗消一些效能(程式直接取值 vs 讀取DB取值,通常還需要加上Cache機制以防效能受拖累)。用或不用,要視各系統的相關條件而定。 由以上的優缺點來分析,當列舉項目預期數年都不會增刪,也沒有必要在純DB端取得對照,則用enum來做,不失為一種符合KISS法則的設計。