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();
        }
    }
}

 

posted @ 2017-10-10 16:25  咕-咚  阅读(1249)  评论(0编辑  收藏  举报