通过重写 class 的 ToString() 来简化获取 enum 的 DescriptionAttribute 值

目录

一、常见的 enum 类型

  新建一个 AlgorithmType 枚举,里面包含 MD5、SHA1 和 SHA2 等一系列的枚举值,默认为 int 类型。有的时候我们会在对应的枚举值上使用特性 [Description] 来添加备注信息,方便我们后期提供描述信息(如返回给前端界面展示时可能需要使用)。

  AlgorithmType.cs

    /// <summary>
    /// 算法类型
    /// </summary>
    public enum AlgorithmType
    {
        /// <summary>
        /// MD5
        /// </summary>
        [Description("Message-Digest Algorithm 5")]
        MD5,

        /// <summary>
        /// SHA1
        /// </summary>
        [Description("Secure Hash Algorithm 1")]
        SHA1,

        /// <summary>
        /// SHA224
        /// </summary>
        [Description("Secure Hash Algorithm 224")]
        SHA224,

        /// <summary>
        /// SHA256
        /// </summary>
        [Description("Secure Hash Algorithm 256")]
        SHA256,

        /// <summary>
        /// SHA384
        /// </summary>
        [Description("Secure Hash Algorithm 384")]
        SHA384,

        /// <summary>
        /// SHA512
        /// </summary>
        [Description("Secure Hash Algorithm 512")]
        SHA512
    }

  常见的一个做法是,编写一个扩展方法来获取 enum 的描述信息:

    public static class EnumExtensionMethods
    {
        /// <summary>
        /// 获取枚举类型的描述信息
        /// </summary>
        public static string GetDescription(this Enum value)
        {
            var type = value.GetType();
            var name = Enum.GetName(type, value);

            if (name == null) return null;

            var field = type.GetField(name);

            if (!(Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute))
            {
                return name;
            }

            return attribute.Description;
        }
    }

  

  因为直接输出枚举值,或者通过枚举类型对应的 ToString() 的方式输出字符串,结果都为它本身的文本值,BCL 也并没有提供快捷的方式去获取描述信息,所以只能通过类似上述的扩展方法来获取 [DescriptionAttribute]。

  

  【分析】因为枚举属于值类型,它不需要在堆上分配空间,并且在计算时(如比较运算)效率相比引用类型更高,所以从性能上枚举类型是占据了绝对的优势;但是由于 BCL 并没有提供快捷方式的去获取 [Description],并且编写对应的获取方法也较为麻烦(其实也不麻烦,因为你会使用程序员的两大法宝:CTRL+C 和 CTRL+V)。

二、演变:class 版本的 enum 类型

  这次我们不直接使用 enum,而是采取新建 class 的方式去模仿 enum 类型,也就是使用引用类型来取代值类型,不过,性能方面会有所损耗。

  HashAlgorithmType.cs

    /// <summary>
    /// 哈希算法类型
    /// </summary>
    public class HashAlgorithmType
    {
        /// <summary>
        /// MD5
        /// </summary>
        );

        /// <summary>
        /// SHA1
        /// </summary>
        );

        /// <summary>
        /// SHA224
        /// </summary>
        );

        /// <summary>
        /// SHA256
        /// </summary>
        );

        /// <summary>
        /// SHA384
        /// </summary>
        );

        /// <summary>
        /// SHA512
        /// </summary>
        );

        private readonly int _hashAlgorithmType;

        private HashAlgorithmType(int hashAlgorithmType)
        {
            _hashAlgorithmType = hashAlgorithmType;
        }

        public override string ToString()
        {
            string result;

            switch (_hashAlgorithmType)
            {
                :
                    result = "Message-Digest Algorithm 5";
                    break;
                :
                    result = "Secure Hash Algorithm 1";
                    break;
                :
                    result = "Secure Hash Algorithm 224";
                    break;
                :
                    result = "Secure Hash Algorithm 256";
                    break;
                :
                    result = "Secure Hash Algorithm 384";
                    break;
                :
                    result = "Secure Hash Algorithm 512";
                    break;
                default:
                    throw new Exception("哈希算法类型有误");
            }

            return result;
        }
    }

  我们采用了 private 进行构造函数私有化的操作,这样就不会允许在类的外部 new 对象了;其次,使用 public static readonly 字段提供给外部进行访问,这样的话就和枚举类型的调用方式一致;最后,我们对 ToString() 方法进行了重写,在 return 的值中返回对应的描述信息。

  这样,我们就可以直接通过 class.field 的方式得到对应枚举值的描述信息。

  【分析】性能受损;但 ToString() 比 GetDescription() 更浅显直白、清晰明了;不过,参数以数字“写死”的方式进行提供也欠妥。

三、演进:class 和 enum 两者共存的版本

  在上一个版本的类中,我们在进行构造函数初始化时直接使用了数字 0~5,并且重写 ToString() 时也是直接使用数字 0~5,除了不直观的因素之外,随着枚举值数量的增加,枚举值和自身描述两者间的对应关系也容易出错。现在,我们尝试以私有嵌套类的形式将 enum 和 class 的两者有机结合起来。

  HashAlgorithmType.cs

    /// <summary>
    /// 哈希算法类型
    /// </summary>
    public class HashAlgorithmType
    {
        /// <summary>
        /// MD5
        /// </summary>
        public static HashAlgorithmType MD5 = new HashAlgorithmType(AlgorithmType.MD5);

        /// <summary>
        /// SHA1
        /// </summary>
        public static readonly HashAlgorithmType SHA1 = new HashAlgorithmType(AlgorithmType.SHA1);

        /// <summary>
        /// SHA224
        /// </summary>
        public static readonly HashAlgorithmType SHA224 = new HashAlgorithmType(AlgorithmType.SHA224);

        /// <summary>
        /// SHA256
        /// </summary>
        public static readonly HashAlgorithmType SHA256 = new HashAlgorithmType(AlgorithmType.SHA256);

        /// <summary>
        /// SHA384
        /// </summary>
        public static readonly HashAlgorithmType SHA384 = new HashAlgorithmType(AlgorithmType.SHA384);

        /// <summary>
        /// SHA512
        /// </summary>
        public static readonly HashAlgorithmType SHA512 = new HashAlgorithmType(AlgorithmType.SHA512);

        /// <summary>
        /// 算法类型
        /// </summary>
        private readonly AlgorithmType _algorithmType;

        private HashAlgorithmType(AlgorithmType algorithmType)
        {
            _algorithmType = algorithmType;
        }

        public override string ToString()
        {
            string result;

            switch (_algorithmType)
            {
                case AlgorithmType.MD5:
                    result = "Message-Digest Algorithm 5";
                    break;
                case AlgorithmType.SHA1:
                    result = "Secure Hash Algorithm 1";
                    break;
                case AlgorithmType.SHA224:
                    result = "Secure Hash Algorithm 224";
                    break;
                case AlgorithmType.SHA256:
                    result = "Secure Hash Algorithm 256";
                    break;
                case AlgorithmType.SHA384:
                    result = "Secure Hash Algorithm 384";
                    break;
                case AlgorithmType.SHA512:
                    result = "Secure Hash Algorithm 512";
                    break;
                default:
                    throw new Exception("哈希算法类型有误");
            }

            return result;
        }

        /// <summary>
        /// 算法类型
        /// </summary>
        private enum AlgorithmType
        {
            /// <summary>
            /// MD5
            /// </summary>
            MD5,

            /// <summary>
            /// SHA1
            /// </summary>
            SHA1,

            /// <summary>
            /// SHA224
            /// </summary>
            SHA224,

            /// <summary>
            /// SHA256
            /// </summary>
            SHA256,

            /// <summary>
            /// SHA384
            /// </summary>
            SHA384,

            /// <summary>
            /// SHA512
            /// </summary>
            SHA512
        }
    }

  在 HashAlgorithmType 类中,新建了一个私有的 AlgorithmType 枚举,这样就只允许 HashAlgorithmType 类访问,而不会在该类的外部(其它类型)进行访问。

  正所谓萝卜青菜,各有所爱,假如你过于关于效率性能,或者说不需要使用诸如 [Description] 附加的特性,也不想额外的增添更多的行为和特征时,我们依然可以采用最原始的、大众化的版本。

通过重写 class 的 ToString() 来简化获取 enum 的 DescriptionAttribute 值的更多相关文章

  1. .Net反射-两种方式获取Enum中的值

    public enum EJobType { 客服 = , 业务员 = , 财务 = , 经理 = } Type jobType = typeof(EJobType); 方式1: Array enum ...

  2. C# 获取Enum 描述和值集合

    //获取枚举的值 public static IEnumerable<T> GetEnumValues<T>() where T : struct { T[] values = ...

  3. request对象常用API 获取请求参数的值 request应用 MVC设计模式

    1 request对象常用API   1)表示web浏览器向web服务端的请求   2)url表示访问web应用的完整路径:http://localhost:8080/day06/Demo1     ...

  4. 安卓Android控件ListView获取item中EditText值

    可以明确,现在没有直接方法可以获得ListView中每一行EditText的值. 解决方案:重写BaseAdapter,然后自行获取ListView中每行输入的EditText值. 大概算法:重写Ba ...

  5. Android控件ListView获取item中EditText值

    能够明白,如今没有直接方法能够获得ListView中每一行EditText的值. 解决方式:重写BaseAdapter,然后自行获取ListView中每行输入的EditText值. 大概算法:重写Ba ...

  6. 获取程序的SHA1值

    android获取程序的SHA1值 public static String getSHA1(Context context) { try { PackageInfo info = context.g ...

  7. 无废话Android之activity的生命周期、activity的启动模式、activity横竖屏切换的生命周期、开启新的activity获取他的返回值、利用广播实现ip拨号、短信接收广播、短信监听器(6)

    1.activity的生命周期 这七个方法定义了Activity的完整生命周期.实现这些方法可以帮助我们监视其中的三个嵌套生命周期循环: (1)Activity的完整生命周期 自第一次调用onCrea ...

  8. Entity Framwork(EF) 7——在Controller内获取指定字段的值

    一.开发背景: 在用户登录的时候,验证用户和密码是否正确.验证通过后将用户名和用户ID保存下来以便后续数据更新时使用. 二.用户验证方法: 1.创建DBContext 对象. ApplicationD ...

  9. jquery attr()方法 添加,修改,获取对象的属性值。

    jquery attr()方法 添加,修改,获取对象的属性值. jquery中用attr()方法来获取和设置元素属性,attr是attribute(属性)的缩写,在jQuery DOM操作中会经常用到 ...

随机推荐

  1. salesforce 零基础学习(六十二)获取sObject中类型为Picklist的field values(含record type)

    本篇引用以下三个链接: http://www.tgerm.com/2012/01/recordtype-specific-picklist-values.html?m=1 https://github ...

  2. C#图片存入数据库及其读出显示

    <1>将图片转换成二进制插入数据库 FileStream fs = new FileStream("D:\\Add.ico",FileMode.Open); byte[ ...

  3. JavaScript笔记基础篇(三)

    针对前段JS获取当前时间或者对时间数据处理方法汇总: javascript 字符串转化为日期 Java代码   var s="2010-5-18 12:30:20"; var t= ...

  4. C语言学习001:让程序跑起来

    编译工具下载 MinGW - Minimalist GNU for Windows 编译运行 #include <stdio.h> int main(){ puts("C roc ...

  5. net-snmp源码VS2013编译添加加密支持(OpenSSL)(在VS里配置编译OpenSSL)

    net-snmp源码VS2013编译添加加密支持(OpenSSL) snmp v3 协议使用了基于用户的安全模型,具有认证和加密两个模块. 认证使用的算法是一般的消息摘要算法,例如MD5/SHA等.这 ...

  6. sssssssss

    构造函数new A 和new A()的区别,都是A类的实例化,后者可以向构造函数传参数. a=f(),指向window a=new f()指向当前函数的实例. Return b和return b()区 ...

  7. shell脚本编写步骤及其常用命令和符号

    1,什么是Shell     Shell 是kernel的一个外壳,是一个命令解析器,负责用户与内核的交互.2,Shell脚本     Shell脚本类似于批处理,可以方便的执行大量命令.3,编写sh ...

  8. 【Java资源免费分享,网盘自己拿】

    JavaSE: Java马士兵:链接:https://pan.baidu.com/s/1jJRvxGi密码:v3xb Java毕向东:链接:https://pan.baidu.com/s/1ggzHk ...

  9. git 依据SHA值提取文件patch

    git format-patch -M master //当前分支所有超前master的提交 git format-patch -s SHA值 //此SHA值提交以后的所有PATCH git form ...

  10. JaveWeb 公司项目(4)----- Easyui的表单验证

    前面三篇博文讲述的是界面的搭建和数据的传输,可以看出目前我做的这个小项目已经有了一个大体的雏形,剩下的就是细节部分的打磨和一些友好的人机交互设计,今天做的是表单的验证,作为初学者,着实花了一番功夫,所 ...