今天和大家分享一个给Enum加备注的技巧,话不多说,先上一段代码:
1 namespace TestReflector.Model.Entities 2 { 3 public class UserInfo 4 { 5 public int Id { get; set; } 6 7 public string Name { get; set; } 8 9 public UserStatusEnum UserStatus { get; set; } 10 } 11 12 public enum UserStatusEnum 13 { 14 /// <summary> 15 /// 待审核 16 /// </summary> 17 WaitAudit, 18 19 /// <summary> 20 /// 审核中 21 /// </summary> 22 Auditing, 23 24 /// <summary> 25 /// 已审核 26 /// </summary> 27 Audited 28 } 29 }
相信大家在项目中都遇到过这种情况吧,用户的状态只是一个枚举,但UI层确需要显示对应的提示信息(例如“待审核”)。
怎样将Enum转换为字符串,写个转换方法?No!!!
下面介绍一种插入元数据的方式来实现此功能,使代码易维护,又不会分散在各个地方:
1. 首先建立一个工具类:
/// <summary> /// 枚举类型扩展方法类 /// </summary> public static class EnumExtention { /// <summary> /// 获取枚举值的详细文本[Description] /// </summary> /// <param name="target"></param> /// <returns></returns> public static string GetDescription(this System.Enum target) { Type t = target.GetType(); //获取字段信息 System.Reflection.FieldInfo[] fieldInfos = t.GetFields(); foreach (System.Reflection.FieldInfo info in fieldInfos) { //判断名称是否相等 if (info.Name != target.ToString()) continue; #region 4.5 ////反射出自定义属性 //var dscript = info.GetCustomAttribute<DescriptionAttribute>(true); ////类型转换找到一个Description,用Description作为成员名称 //if (dscript != null) // return dscript.Description; #endregion #region 3.5 //反射出自定义属性 foreach (Attribute attr in info.GetCustomAttributes(true)) { //类型转换找到一个Description,用Description作为成员名称 var dscript = attr as DescriptionAttribute; if (dscript != null) return dscript.Description; } #endregion } //如果没有检测到合适的注释,则用默认名称 return target.ToString(); } }
2.第二步,我们来修改原来的UserStatusEnum:
1 public enum UserStatusEnum 2 { 3 /// <summary> 4 /// 待审核 5 /// </summary> 6 [Description("待审核")] 7 WaitAudit, 8 9 /// <summary> 10 /// 审核中 11 /// </summary> 12 [Description("审核中")] 13 Auditing, 14 15 /// <summary> 16 /// 已审核 17 /// </summary> 18 [Description("已审核")] 19 Audited 20 }
不要忘记导入命名空间:
using System.ComponentModel;
3. OK,准备工作已经做好了,使用方法如下:
1 class Program 2 { 3 private static void Main(string[] args) 4 { 5 var userStatus = UserStatusEnum.Auditing; 6 7 string strUserStatus = userStatus.GetDescription(); 8 9 Console.WriteLine(strUserStatus); 10 11 Console.ReadKey(); 12 } 13 }
4. 输出结果:
5. 到了现在已经可以告一段落了,我们的小工具已经实现了需要的功能。但反射的效率如何呢?
我可以告诉大家的是:效率不堪入目。。。
6. 优化效率:
反射的耗时操作在于搜索元数据,我们可以将搜索出的MethodInfo、FieldInfo缓存一下,以达到提升效率的目的。
下面是我优化过后的结果:
7.可以看出。优化过后的代码执行效率提升了10倍左右。好了,今天的文章分享到这里,希望可以给大家带来方便。
1 /// <summary> 2 /// 枚举类型扩展方法类 3 /// </summary> 4 public static class EnumExtention 5 { 6 private static readonly Dictionary<RuntimeTypeHandle, FieldInfo[]> CacheFieldInfo = new Dictionary<RuntimeTypeHandle, FieldInfo[]>(); 7 private static readonly Dictionary<string, DescriptionAttribute> CacheDescriptionAttr = new Dictionary<string, DescriptionAttribute>(); 8 9 /// <summary> 10 /// 获取枚举值的详细文本[Description] 11 /// </summary> 12 /// <param name="target"></param> 13 /// <returns></returns> 14 public static string GetDescription(this System.Enum target) 15 { 16 Type t = target.GetType(); 17 var typeHandle = t.TypeHandle; 18 string strTarget = Enum.GetName(t, target); 19 20 //获取字段信息 21 System.Reflection.FieldInfo[] arrFieldInfo; 22 if (CacheFieldInfo.ContainsKey(typeHandle)) 23 { 24 arrFieldInfo = CacheFieldInfo[typeHandle]; 25 } 26 else 27 { 28 arrFieldInfo = t.GetFields(); 29 CacheFieldInfo[typeHandle] = arrFieldInfo; 30 } 31 32 for (int i = arrFieldInfo.Length - 1; i >= 0; i--) 33 { 34 var fieldInfo = arrFieldInfo[i]; 35 36 //判断名称是否相等 37 if (fieldInfo.Name != strTarget) continue; 38 39 #region 3.5 40 41 //反射出自定义属性 42 if (CacheDescriptionAttr.ContainsKey(strTarget)) 43 { 44 var dscript = CacheDescriptionAttr[strTarget]; 45 return dscript.Description; 46 } 47 else 48 { 49 var arrAttr = fieldInfo.GetCustomAttributes(true); 50 for (int j = arrAttr.Length - 1; j >= 0; j--) 51 { 52 var attr = arrAttr[j]; 53 //类型转换找到一个Description,用Description作为成员名称 54 var dscript = attr as DescriptionAttribute; 55 if (dscript != null) 56 { 57 CacheDescriptionAttr[strTarget] = dscript; 58 return dscript.Description; 59 } 60 } 61 } 62 63 #endregion 3.5 64 } 65 66 //如果没有检测到合适的注释,则用默认名称 67 return strTarget; 68 } 69 }