zoukankan      html  css  js  c++  java
  • [C#] 通过重写 class 的 ToString() 来简化获取 enum 的 DescriptionAttribute 值

    通过重写 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>
            public static readonly HashAlgorithmType MD5 = new HashAlgorithmType(0);
    
            /// <summary>
            /// SHA1
            /// </summary>
            public static readonly HashAlgorithmType SHA1 = new HashAlgorithmType(1);
    
            /// <summary>
            /// SHA224
            /// </summary>
            public static readonly HashAlgorithmType SHA224 = new HashAlgorithmType(2);
    
            /// <summary>
            /// SHA256
            /// </summary>
            public static readonly HashAlgorithmType SHA256 = new HashAlgorithmType(3);
    
            /// <summary>
            /// SHA384
            /// </summary>
            public static readonly HashAlgorithmType SHA384 = new HashAlgorithmType(4);
    
            /// <summary>
            /// SHA512
            /// </summary>
            public static readonly HashAlgorithmType SHA512 = new HashAlgorithmType(5);
    
            private readonly int _hashAlgorithmType;
    
            private HashAlgorithmType(int hashAlgorithmType)
            {
                _hashAlgorithmType = hashAlgorithmType;
            }
    
            public override string ToString()
            {
                string result;
    
                switch (_hashAlgorithmType)
                {
                    case 0:
                        result = "Message-Digest Algorithm 5";
                        break;
                    case 1:
                        result = "Secure Hash Algorithm 1";
                        break;
                    case 2:
                        result = "Secure Hash Algorithm 224";
                        break;
                    case 3:
                        result = "Secure Hash Algorithm 256";
                        break;
                    case 4:
                        result = "Secure Hash Algorithm 384";
                        break;
                    case 5:
                        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] 附加的特性,也不想额外的增添更多的行为和特征时,我们依然可以采用最原始的、大众化的版本。

  • 相关阅读:
    Burp suite
    CTF 压缩包分析
    PHP代码审计
    SQL注入
    常考文件包含漏洞
    PHP黑魔法
    CTF WEB笔记
    MsSQL数据库提权
    ATT&CK实战系列
    Linux访问控制
  • 原文地址:https://www.cnblogs.com/liqingwen/p/8415440.html
Copyright © 2011-2022 走看看