[.Net] 通过反射,给Enum加备注

  今天和大家分享一个给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. 首先建立一个工具类:

 1     /// <summary>
 2     /// 枚举类型扩展方法类
 3     /// </summary>
 4     public static class EnumExtention
 5     {
 6         /// <summary>
 7         /// 获取枚举值的详细文本[Description]
 8         /// </summary>
 9         /// <param name="target"></param>
10         /// <returns></returns>
11         public static string GetDescription(this System.Enum target)
12         {
13             Type t = target.GetType();
14             //获取字段信息
15             System.Reflection.FieldInfo[] fieldInfos = t.GetFields();
16             foreach (System.Reflection.FieldInfo info in fieldInfos)
17             {
18                 //判断名称是否相等
19                 if (info.Name != target.ToString()) continue;
20
21                 #region 4.5
22                 ////反射出自定义属性
23                 //var dscript = info.GetCustomAttribute<DescriptionAttribute>(true);
24                 ////类型转换找到一个Description,用Description作为成员名称
25                 //if (dscript != null)
26                 //    return dscript.Description;
27                 #endregion
28
29                 #region 3.5
30                 //反射出自定义属性
31                 foreach (Attribute attr in info.GetCustomAttributes(true))
32                 {
33                     //类型转换找到一个Description,用Description作为成员名称
34                     var dscript = attr as DescriptionAttribute;
35                     if (dscript != null)
36                         return dscript.Description;
37                 }
38                 #endregion
39             }
40
41             //如果没有检测到合适的注释,则用默认名称
42             return target.ToString();
43         }
44
45     }

  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      }

时间: 2024-12-20 04:16:14

[.Net] 通过反射,给Enum加备注的相关文章

执行sql在一个表中添加字段,加备注

1.加字段: alter table 表名 ADD 字段名 类型; eg: alter table sys_cwzd ADD SCCLLJ VARCHAR2(50); 2.加备注: comment on column 表名.字段名 is '备注名'; eg:comment on column sys_cwzd.SCCLLJ is '上传材料路径'; 原文地址:https://www.cnblogs.com/Cuimc/p/11412191.html

Java反射之静态加载和动态加载举例小记

静态加载: package com.imooc.加载类; public class Office_Static { public static void main(String[] args) { //new 创建对象,是静态加载类,在编译时刻就需要加载所有的可能使用到的类 if("Word".equals(args[0])){ Word w = new Word(); w.start(); } if("Excel".equals(args[0])){ Excel

oracle数据库之 创建表以及给表和字段加备注

一.comment是oracle数据库系统的关键字,所以能用来命名表明或字段名 二.comment关键字用于对表,字段添加注释,有利于用户对表结构以及数据库对象含义的理解. 三.用户可以通过数据字典视图来查询表或字段的数据信息,可查询的相应视图为:1. 访问自己用户的注释信息要查询的数据字典视图(the date directory views)user_tab_comments;表注释:有三个字段TABLE_NAME,TABLE_TPYE,COMMENTSuser_col_comments;表

如何通过反射实现动态功能模块加载

程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象.您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性. 下面我们将介绍如何通过不使用反射的方式和使用反射的方式加载功能模块.实现效果: 1.        WinForm 主程序 主程序我们使用Winform程序,VS2008 工具C#语言开发.包括工具栏.状态栏及TabControl控件.我们使用TabControl 作为功能模块容器

[转] 通过反射实现动态功能模块加载

原文 如何通过反射实现动态功能模块加载 程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象.您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性. 下面我们将介绍如何通过不使用反射的方式和使用反射的方式加载功能模块.实现效果: 1. WinForm 主程序 主程序我们使用Winform程序,VS2008 工具C#语言开发.包括工具栏.状态栏及TabControl控件.我们使用TabCon

仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢?

原文:仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢? 平时我们获取一个程序集或者类型的 Attribute 是非常轻松的,只需要通过 GetCustomAttribute 方法就能拿到实例然后获取其中的值.但是,有时我们仅为反射加载一些程序集的时候,获取这些元数据就不那么简单了,因为我们没有加载目标程序集中的类型. 本文介绍如何为仅反射加载的程序集读取 Attribute 元数据信息. 本文内容 仅反射加载一个程序

JavaEE基础(二十七)/反射、JDK新特性

1.反射(类的加载概述和加载时机) A:类的加载概述 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 加载  就是指将class文件读入内存,并为之创建一个Class对象.任何类被使用时系统都会建立一个Class对象. 连接 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数据中的符号引用替换为直接引用 初始化 就是我们以前讲过的初始化步骤 B:加载时机 创建类

SparkConf加载与SparkContext创建(源码)

即日起开始spark源码阅读之旅,这个过程是相当痛苦的,也许有大量的看不懂,但是每天一个方法,一点点看,相信总归会有极大地提高的.那么下面开始: 创建sparkConf对象,那么究竟它干了什么了类,从代码层面,我们可以看到我们需要setMaster啊,setAppName啊,set blabla啊...等等~ val sparkConf = new SparkConf().setMaster("local").setAppName("TopActiveLocations&qu

实现Android 动态加载APK(Fragment or Activity实现)

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38565345 最近由于项目太大了,导致编译通不过(Android对一个应用中的方法个数貌似有限制),所以一直琢磨着能否将某些模块的APK不用安装,动态加载,通过在网上查找资料和网友的帮助,终于实现了APK的动态加载,网络上介绍APK动态加载的文章非常多,但是我觉得写得非常好的就是这位大牛的,我基本上就是使用他的这种方案,然后加入了自己的元素.这位大牛是通过Activity实现的,我稍作修改