c# 反射+Attribute 实现获取Description的两种做法
直接看到代码,其中代码和文字描述都在里面;
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; //题目就是attribute 反射 中间缓存; //为啥缓存的key 是我们的type 类型呢? //首先会定义我们的一个基本的attribute属性,其实net中已经自带这个功能; [AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum)] public class PropertyDesc :Attribute { public string Desc { get; private set; } public PropertyDesc(string propertyDescription) { Desc = propertyDescription; } } //枚举数据类型的结构; public enum Product:byte { [PropertyDesc("电脑")] computer =1, [PropertyDesc("电视")] Tv =2 } public class User { public string Name { get; set; } } //可以最终写成我们的额动态扩展的东西滴呀; //获取的是指定的类型的数据; public class enumHelper<T> where T:class { private static Dictionary<Type, Dictionary<string, string>> _cache = new Dictionary<Type, Dictionary<string, string>>(); /// <summary> /// 这种做法不是特别完美,但是,效果还是比较好的; /// </summary> /// <param name="p"></param> /// <returns></returns> public static string GetEnumDescription(object p) { Type t = p.GetType(); if (!_cache.ContainsKey(t)) { GetAndSaveCacheEnumDescription<T>(t); } var dic = _cache[t]; var fieldName = p.ToString(); var result = dic.ContainsKey(fieldName)?dic[fieldName]:$"Can not find {fieldName} description"; return result; } private static void GetAndSaveCacheEnumDescription<T>(Type t) { var fields = t.GetFields(); //一次性取出所有枚举字段; var dic = new Dictionary<string, string>(); _cache.Add(t, dic); foreach (var item in fields) { var objs = item.GetCustomAttributes(typeof(T),false); //获取到自定的属性 if (objs.Length > 0) //排除自动属性生成的东西 { T obj = (T)objs[0]; //只定义了一个属性 => 并强制转换成了 PropertyDesc Type attrType = obj.GetType(); // 继续反射 PropertyInfo pi = attrType.GetProperty("Desc"); //获取指定的属性 string value = pi.GetValue(obj,null).ToString(); //获取指定属性的值 dic.Add(item.Name,value); //添加到字典; } } } } /// <summary> /// 似乎,我们的额版本二更为强大一些; /// </summary> public static class EnumExtensions { //自然就有我们的 优化版本的东西滴呀; 线程安全,并且带自定扩展方法的操作,十分完美的集合; private static ConcurrentDictionary<Type, Dictionary<object, string>> _cache = new ConcurrentDictionary<Type, Dictionary<object, string>>(); public static string GetDescription(this Enum value) { if (value == null) { return string.Empty; } string val = value.ToString(); //在首次载入添加页面的时候,有些数据可能未空,所以这里必要时添加判断 if(string.IsNullOrEmpty(val) || val == "0") { return string.Empty; } string fielName = value.ToString(); var type = value.GetType(); Dictionary<object, string> nameDescriptions = null; nameDescriptions = _cache.GetOrAdd(type,(tempType) => { Dictionary<object, string> temp = new Dictionary<object, string>(); //获取枚举中的所有值;(字段值) var enmus = Enum.GetValues(tempType); foreach (var en in enmus) { var field = tempType.GetField(Enum.GetName(tempType,en)); //指定的字段; 等同于 en.ToString() //获取每一个枚举值中的description attribute //获取到指定的field; if (field != null) { //获取指定字段的自定义属性; var des = Attribute.GetCustomAttribute(field,typeof(DescriptionAttribute)) as DescriptionAttribute; if (des != null) { temp.Add(en,des.Description); } else { temp.Add(en,Convert.ToString(en)); } } } return temp; }); string description = null; //大致的思路都是先将所有的枚举description(一次性将所有的)加入我们的 cache 中,然后再从中取出; nameDescriptions.TryGetValue(value,out description); return description; } } namespace ConsoleApplication58 { class Program { static void Test() { var a=enumHelper<PropertyDesc>.GetEnumDescription(Product.computer); var b=enumHelper<PropertyDesc>.GetEnumDescription(Product.computer); var c = enumHelper<PropertyDesc>.GetEnumDescription(Product.Tv); var d = enumHelper<PropertyDesc>.GetEnumDescription(Product.Tv); Console.WriteLine(a); Console.WriteLine(b); Console.WriteLine(c); Console.WriteLine(d); Console.WriteLine("-----------------"); //DescriptionAttribute 是我们组件中 一个封装好的 继承自我们的Attribute 中的一个类; Console.WriteLine(Product.computer.GetDescription()); } static void Main(string[] args) { Test(); Console.ReadLine(); } } }