zoukankan      html  css  js  c++  java
  • Enum是如何用的?

    Enum是如何用的?

    一、前言

    对于枚举Enum,大家都非常熟悉,但枚举出现的场景非常多的时候,是不是可以抽象出一个通用的解决方式。代码大家都会写,但并不是所有人都喜欢写重复的代码,老是用Ctrl+C和Ctrl+V累不累啊?很多人和我一样,非常不喜欢写重复的代码,代码写多了,BUG就多。对于常见的场景,大部分人都喜欢抽象出来,写一套通用的,每个地方都可以用,而且不易出错。当然,你喜欢Ctrl+C和Ctrl+V,本人也没有办法....

    二、int值,string值转换成Enum

    如下,一个简单枚举:

    复制代码
        public enum ExchangeType
        {
            [EnumFieldAttribute("不限", true)] 
            All = 0,
            [EnumFieldAttribute("深圳证券交易所")]
            SZSE = 1
        }
    复制代码

    对于以下输入代码:

    复制代码
                ExchangeType type = (ExchangeType)3;
    
                if (type == ExchangeType.All)
                {
                    Console.WriteLine("ExchangeType.All.");
                }
                else if (type == ExchangeType.SZSE)
                {
                    Console.WriteLine("ExchangeType.SZSE.");
                }
                else
                {
                    Console.WriteLine("Non Exist!");
                }
    复制代码

    对于强制转换,大家猜猜看,会输出什么....

    对于结果,大家可以自己去测试下,有可能与你期望的值不一致!

    同样对于以下代码:

    ExchangeType type;
    bool success = Enum.TryParse<ExchangeType>("3", out  type);

    TryParse执行的返回结果success也是成功的(为true),但期望值也不一定正确。

    因此,对于枚举转换来说,还是很容易出错的。所以,必须提供默认的值来确保转换失败时,返回正确的值。对于int值和string值转换成Enum的代码如下:

    复制代码
            public static T ToEnum<T>(int value, T defaultT) where T : struct
            {
                string enumName = Enum.GetName(typeof(T), value);
    
                return ToEnum<T>(enumName, defaultT);
            }
    
            public static T ToEnum<T>(string enumName, T defaultT) where T : struct
            {
                if (string.IsNullOrWhiteSpace(enumName))
                {
                    return defaultT;
                }
    
                T result;
    
                if (!Enum.TryParse<T>(enumName.Trim(), out result))
                {
                    return defaultT;
                }
    
                if (Enum.IsDefined(typeof(T), result))
                {
                    return result;
                }
    
                return defaultT;
            }
    复制代码


    另外还提供了其他应用的方法,如将包含类型名称前缀的字符串ExchangeType.All转换成枚举,同样需要提供默认值来确保转换结果的准确性,代码如下:

    复制代码
            public static T TryParse<T>(string typeValue, T defaultValue, bool containsTypeName = false) where T : struct
            { 
                typeValue = (typeValue ?? string.Empty).Trim();
    
                if (containsTypeName)
                {
                    int startIndex = typeValue.IndexOf(".");
    
                    if (startIndex > 0 && typeValue.Length > startIndex + 1)
                    {
                        typeValue = typeValue.Substring(startIndex + 1);
                    }
                }
    
                return ToEnum<T>(typeValue, defaultValue);
            }
    复制代码

    应用的话,比较简单,ExchangeType type = EnumFieldProvider.TryParse<ExchangeType>("ExchangeType.", ExchangeType.All, true);

    三、高级应用通用方式

    对于下拉列表中,很多场景与枚举有关,硬编码也可以直接绑定。但是枚举很多的时候是不是得写很多代码,而且并不一定保证代码的正确性。与其这样,那就写一个通用的吧,大家都轻松:

    复制代码
            public static EnumFieldAttribute GetEnumAttribute(Type type)
            {
                if (type == null)
                {
                    return null;
                }
    
                object[] customAttributes = type.GetCustomAttributes(typeof(EnumFieldAttribute), true);
                EnumFieldAttribute attribute = null;
    
                foreach (object attr in customAttributes)
                {
                    attribute = attr as EnumFieldAttribute;
    
                    if (attribute != null)
                    {
                        return attribute;
                    }
                }
    
                return null;
            }
    
            public static IList<EnumItem<T>> GetItems<T>(bool isSpecialRequired = false) where T : struct
            {
                var fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
    
                if (fields == null || fields.Count() == 0)
                {
                    return new List<EnumItem<T>>();
                }
    
                var enumItems = new List<EnumItem<T>>();
                EnumFieldAttribute attribute = null;
                T currentValue;
    
                foreach (var field in fields)
                {
                    object[] customAttributes = field.GetCustomAttributes(typeof(EnumFieldAttribute), true);
                    foreach (object attr in customAttributes)
                    {
                        attribute = attr as EnumFieldAttribute;
    
                        if (attribute != null)
                        {
                            if (attribute.IsSpecialRequired)
                            {
                                if (!isSpecialRequired)
                                {
                                    continue;
                                }
                            }
    
                            currentValue = (T)field.GetValue(null);
    
                            enumItems.Add(new EnumItem<T>(currentValue, attribute.Desc));
                        }
                    } 
                }
    
                return enumItems;
            }
    
            public static IList<EnumItem<T>> GetItems<T>(IList<T> entities) where T : struct
            {
                if (entities == null || entities.Count() == 0)
                {
                    return new List<EnumItem<T>>();
                }
    
                var enumItems = new List<EnumItem<T>>();
    
                foreach (var entity in entities)
                {
                    enumItems.Add(GetItem<T>(entity));
                }
    
                return enumItems;
            }
    
            public static string GetItemDescription<T>(T enumItem) where T : struct
            {
                var field = typeof(T).GetField(enumItem.ToString());
    
                if (field == null)
                {
                    return string.Empty; 
                }
    
                object[] customAttributes = field.GetCustomAttributes(typeof(EnumFieldAttribute), true);
                foreach (object attr in customAttributes)
                {
                    EnumFieldAttribute attribute = attr as EnumFieldAttribute;
    
                    if (attribute != null)
                    {
                        return attribute.Desc;
                    }
                }
    
                return string.Empty; 
            }
    
            public static EnumItem<T> GetItem<T>(T enumItem) where T : struct
            {
                var field = typeof(T).GetField(enumItem.ToString());
    
                if (field == null)
                {
                    return new EnumItem<T>(enumItem, enumItem.ToString());
                }
    
                object[] customAttributes = field.GetCustomAttributes(typeof(EnumFieldAttribute), true);
                foreach (object attr in customAttributes)
                {
                    EnumFieldAttribute attribute = attr as EnumFieldAttribute;
    
                    if (attribute != null)
                    {
    return new EnumItem<T>(enumItem, attribute.Desc);
                    }
                }
    
                return new EnumItem<T>(enumItem, enumItem.ToString());
            }
    复制代码

    对于方法public static IList<EnumItem<T>> GetItems<T>(bool isSpecialRequired = false) where T : struct,提供一个参数来筛选是否需要该参数,如以上定义的枚举类型ExchangeType中的 EnumFieldAttribute("不限", true),其中EnumFieldAttribute("不限", true)第二个参数与isSpecialRequired参数一致。
    测试代码如下:

    复制代码
            [TestMethod()]
            public void GetItemsTest()
            {
                IList<EnumItem<ExchangeType>> actual = EnumFieldProvider.GetItems<ExchangeType>(true);
                Assert.AreEqual(actual.Count, 2);
                Assert.AreEqual(actual[0].Value, ExchangeType.All);
                Assert.AreEqual(actual[1].Value, ExchangeType.SZSE);
            }
    
            [TestMethod()]
            public void GetItemsWithFalseArgTest()
            { 
                IList<EnumItem<ExchangeType>> actual = EnumFieldProvider.GetItems<ExchangeType>();
                Assert.AreEqual(actual.Count, 1);
                Assert.AreEqual(actual[0].Value, ExchangeType.SZSE);
            }
    复制代码

    返回的结果可以用于下拉列表,ListBox等相关控件值的绑定与显示(由于明天还得上班,本文不提供,下篇随笔提供)。

    四、总结

    对于细节方面,还是需要花时间和精力来总结的。用得多了,自然也就懂了,洗洗睡觉了...

    今天又是7月1号,又是一个纪念日。4年前,6月26号毕业联欢晚会后,哥开始正式工作的第一天也是7月1号。一转眼,4年过去了,人生如戏...

    作者:JasenKin
    出处:http://www.cnblogs.com/jasenkin/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     
    标签: EnumFiledProvider
  • 相关阅读:
    C#Table转成json工具
    设置npm注册表配置为淘宝镜像
    总结js面向对象调用的几种模式
    gitHub初使用
    对象的防篡改
    offsetWidth clientWidth scrollWidth的区别
    js中的new操作符
    setTimeot与setInterval定时器
    事件捕获 事件冒泡和事件委托
    一个页面从输入URL到加载完成,发生什么事
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3164337.html
Copyright © 2011-2022 走看看