CODE-將CHAR(1)欄位轉換為列舉型別
3 |
工作上常遇到的需求:
旗標性質欄位在資料庫被定義成CHAR(1),用單一字元代表不同意義,例如: 1=新增、2=修改、3=刪除、A=同意、R=同意、W=撤回、C=取消。針對這類旗標,UI常會使用下拉選單或Radio Button列出選項讓使用者選取;而在顯示時需將資料庫讀到的"A"轉成"同意"方便理解。
實作時,我偏好在ViewModel將這種欄位屬性定義成.NET列舉(Enum)型別,UI上直接用列舉項目當作下拉選單選項,利用每個列舉項目都有對應int值的特性,直接將各項目對應成要存入的字元,例如:
public enum MyEnum
{
新增 = 1,
修改 = 2,
刪除 = 3,
同意 = (int)'A',
否決 = (int)'R',
撤回 = (int)'W',
取消 = (int)'C'
}
如此便能很方便地在列舉型別與CHAR(1)字元間互轉--如果有一個好用的工具函數的話!
以下就是我心中好用的工具函數:
//參考: http://bit.ly/16yoItk
/// <summary>
/// 將列舉值轉為列舉型別
/// </summary>
/// <typeparam name="T">列舉型別</typeparam>
/// <param name="value">列舉值字串</param>
/// <returns></returns>
public static T GetEnum<T>(string value) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
int n;
//若非數字時且為單一字母,將其轉為CHAR
if (!int.TryParse(value, out n) && value.Length == 1)
value = ((int)value[0]).ToString();
return ((T)Enum.Parse(typeof(T), value));
}
/// <summary>
/// 將列舉型別轉為列舉值,可為數字或字元(ex: 1='1',65='A')
/// </summary>
/// <typeparam name="T">列舉型別</typeparam>
/// <typeparam name="R">傳回型別,限int, char或string</typeparam>
/// <param name="enumVal">列舉參數</param>
/// <returns></returns>
public static R GetEnumValue<T, R>(T enumVal) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
Type resType = typeof(R);
if (resType != typeof(int) && resType != typeof(char)
&& resType != typeof(string))
throw new ArgumentException("R must be int, char or string");
int n = enumVal.ToInt32(null);
//R is int時,直接傳回數字
if (resType == typeof(int))
return (R)Convert.ChangeType(n, resType);
//否則轉為Char後傳回(小於10則直接傳數字字元)
char c = n < 10 ? n.ToString()[0] : (char)n;
return (R)Convert.ChangeType(c, resType);
}
實地測試:
protected void Page_Load(object sender, EventArgs e)
{
foreach (MyEnum me in Enum.GetValues(typeof(MyEnum)))
{
//針對每個列舉項目取得int及string
Response.Write(string.Format("<li>{0} / {1} / {2}",
me, Common.GetEnumValue<MyEnum, int>(me),
Common.GetEnumValue<MyEnum, string>(me)));
}
foreach (char c in "123ARWC")
{
//將單一字元轉為列舉
Response.Write(string.Format("<li>{0} -> {1}",
c, Common.GetEnum<MyEnum>(c.ToString())));
}
Response.End();
}
測試成功!!
新增 / 1 / 1 修改 / 2 / 2 刪除 / 3 / 3 同意 / 65 / A 取消 / 67 / C 否決 / 82 / R 撤回 / 87 / W 1 -> 新增 2 -> 修改 3 -> 刪除 A -> 同意 R -> 否決 W -> 撤回 C -> 取消
Comments
# by 小黑
滿屌的~
# by Davidson
最近剛好有遇,感謝好方法。 我只有想到懶人方法 Orz.... 從 SQL 下手 ~_~ public enum MyEnum { 新增 = '1', 修改 = '2', 刪除 = '3', 同意 = 'A', 否決 = 'R', 撤回 = 'W', 取消 = 'C' } INSERT 的時候將該欄位值利用 SQL語法 CHAR(@InsValue) QUERY 的時候透過 ASCII(FieldName) as [FieldName] 來取得 透過這樣的畸形方式,就可結合 Dapper 自動轉換了,但是就是 查詢語法不漂亮 XDD 分享參考 ^^
# by Jeffrey
to Davidson, 這解法有創意,感謝分享。