数据库中经常会出现这样的设计,状态会定义为0、1、2这样的数字,例如审核状态:0审核中、1审核通过、2审核失败。这样的字段对应到程序中一般会定义成枚举类型,对于枚举我们一般定义如下。
/// <summary> /// 审核状态(0:审核中;1:审核成功;2:审核失败) /// </summary> public enum AuditStatus { /// <summary> /// 审核中 /// </summary> Auditing = 0, /// <summary> /// 审核成功 /// </summary> AuditSuccess = 1, /// <summary> /// 审核失败 /// </summary> AuditFail = 2 }
这样我们在页面显示时最多可以取到枚举的名称,但大多数情况我们需要显示的是中文描述。为实现这种需求目前大多是在绑定数据的时候做判断解析,这样做如果中文描述改变了,要改变起来是很痛苦的,每个使用的地方得去修改解析。今天就遇到了这样的问题,于是想办法解决下。
使用特性
1、为枚举值加上特性,Description的命名空间是System.ComponentModel。
/// <summary> /// 审核状态(0:审核中;1:审核成功;2:审核失败) /// </summary> public enum AuditStatus { /// <summary> /// 审核中 /// </summary> [Description("审核中")] Auditing = 0, /// <summary> /// 审核成功 /// </summary> [Description("审核成功")] AuditSuccess = 1, /// <summary> /// 审核失败 /// </summary> [Description("审核失败")] AuditFail = 2 }
2、然后通过反射得到中文描述,这里使用了扩展方法方便调用。
/// <summary> /// 扩展方法,用于获取枚举的中文描述信息 /// </summary> /// <param name="val">枚举值</param> /// <returns>中文描述</returns> public static string GetDesc(this Enum val) { Type type = val.GetType(); string name = Enum.GetName(type, val); object[] objs = type.GetField(name).GetCustomAttributes(typeof(DescriptionAttribute), false);//获取枚举项的特性 if (objs.Length > 0) return (objs[0] as DescriptionAttribute).Description; else return name;//Description特性不存在时返回枚举名 }
3、接下来就可以方便的获取中文描述了,注意调用扩展方法GetDesc前需要保证引用了GetDesc所在的命名空间。
string desc = AuditStatus.Auditing.GetDesc();
使用缓存
使用特性后是可以方便的获取到中文描述,但是这个过程中使用到了反射,而反射对性能多少是有影响的,况且是每个枚举值获取它对应的中文描述时都需要进行一次反射。于是进行了以下改进,增加了缓存。由于缓存各家有不同的使用方法,但都会有读取和写入的方法,所以具体的代码我省去了。这样修改后可以在获取任意枚举值时就直接缓存了这个枚举的所有中文描述,这样不用对每个枚举值使用缓存,然后在通过key(即枚举名称)获得对应的中文描述。
/// <summary> /// 扩展方法,用于获取枚举的中文描述信息 /// </summary> /// <param name="val">枚举值</param> /// <returns>中文描述</returns> public static string GetDesc(this Enum val) { Type type = val.GetType(); string name = Enum.GetName(type, val); return GetAttributes(type)[name]; } /// <summary> /// 获取某枚举的中文描述字典,首次获取时创建缓存记录,后期获取时优先查找缓存中的数据 /// </summary> /// <param name="type">枚举</param> /// <returns>枚举的中文描述字典</returns> public static Dictionary<string, string> GetAttributes(Type type) { Dictionary<string, string> dict = new Dictionary<string, string>(); object[] objs = null; //先从缓存中查找,若无数据则执行以下代码 foreach (var item in type.GetFields()) { if (!item.IsLiteral)//此处过滤了编译过程中产生的一个Field,一开始还没发现,感觉很奇怪为啥会在编译的时候多了一个Field continue; objs = item.GetCustomAttributes(typeof(DescriptionAttribute), false);//获取枚举项的特性 if (objs.Length > 0) dict.Add(item.Name, (objs[0] as DescriptionAttribute).Description); else dict.Add(item.Name, item.Name); } //将字典存入缓存 return dict; }