• C#反射(Reflection)与特性(Attribute)实例


    1.场景:在对接接口遇到Post(multipart/form-data)提交数据时对接的参数名称出现如“model.no”格式的参数。。

    2.思路:看到这种第一时间想到的是最简单快捷的 在写name名的时候直接写“model.no”。但往往实际业务中参数需要进行加密,一般我们把加密方法写好传入字典类(Dictionary)循环取值加密,今天我这里写了一个参数Model。

    3.操作

       3.1 用字典类操作方法(可以在加密的时候进行为空判断): 

            

      3.2 使用的实体类,但实体类的属性命名是不能带小数点的。方法一“model.no”换成“model_no“,循环取值时用String..Replace("-",".")。方法二使用特性在属性上标记表单提交时参数的名称。这里使用的是方法二。

        创建特性FormDataName

        /// <summary>
        /// 表单提交时用的参数名
        /// </summary>
        public class FormDataNameAttribute : Attribute
        {
            public FormDataNameAttribute(String parameterNmae)
            {
                this.ParameterNmae = parameterNmae;
            }
    
            public String ParameterNmae { get; private set; }
        }
    FormDataNameAttribute

      创建反射方法,根据传入的实体生成对应的表单提交格式数据(这里创建了一个model接收返回的数据,也可以用字典类)。

    /// <summary>
            /// 只支持嵌套一层list的实体
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="model"></param>
            /// <returns></returns>
            public List<PostDataClass> convertData<T>(T model)
            {
                List<PostDataClass> postList = new List<PostDataClass>();
                foreach (System.Reflection.PropertyInfo p in model.GetType().GetProperties())
                {
                    if (p.GetValue(model) == null)
                        continue;
                    if (!p.PropertyType.IsGenericType)
                    {
                        //获取字段特性
                        object[] objAttrs = p.GetCustomAttributes(typeof(FormDataNameAttribute), true);
                        //有特性则取特性值作为参数名
                        string prop = objAttrs.Length > 0 ? ((FormDataNameAttribute)objAttrs[0]).ParameterNmae : p.Name.ToString();
                        //字段值
                        string value = p.GetValue(model).ToString();
                        postList.Add(new PostDataClass(prop, value, 0));
                    }
                    else
                    {
                        // 如List<T>,返回类名T
                        string className = p.PropertyType.GetGenericArguments()[0].Name;
                        // 获取该泛型属性值,返回一个列表,如List<Man>;
                        // 因为是反射返回的数据,无法直接转换为List使用,针对这种数据,反射机制对这种属性值提供了
                        // “Count”列表长度、“Item”子元素等属性;
                        object obj = p.GetValue(model, null);
                        // 获取列表List<T>长度
                        int count = Convert.ToInt32(obj.GetType().GetProperty("Count").GetValue(obj, null));
                        for (int i = 0; i < count; i++)
                        {
                            // 获取列表子元素,然后子元素其实也是一个类,然后递归调用当前方法获取类的所有公共属性
                            object item = obj.GetType().GetProperty("Item").GetValue(obj, new object[] { i });
    
                            //重复操作
                            foreach (System.Reflection.PropertyInfo p1 in item.GetType().GetProperties())
                            {
                                if (p1.GetValue(item) == null)
                                    continue;
                                if (!p1.PropertyType.IsGenericType)
                                {
                                    object[] objAttrs = p1.GetCustomAttributes(typeof(FormDataNameAttribute), true);
                                    string prop = objAttrs.Length > 0 ? ((FormDataNameAttribute)objAttrs[0]).ParameterNmae : p1.Name.ToString();
                                    string value = p1.GetValue(item).ToString();
                                    postList.Add(new PostDataClass(prop, value, 0));
                                }
                            }
                        }
                    }
                }
                return postList;
            }
    ReflectData
    PostDataClass是我这需要返回的实体类,实际可根据不同需要反射成不同的数据格式。主要思路是先反射实体,判断数据不为空就且类型非泛型类型就直接取属性名与值。如果是泛型的话使用GetProperty("Count")获取数据的数量与GetProperty("Item")获取数据值,拿到数据之后再循环去里面找数据不为泛型的直接取值,是泛型的再去循环。目前需求只嵌套了一层所以就没判断泛型里面还有泛型的情况。
  • 相关阅读:
    跳跃游戏1,2
    重叠子区间问题
    最长公共子序列问题
    由leetcode俄罗斯套娃信封问题到C++的sort()函数学习
    一道笔试题,做的很垃圾
    Spring boot框架快速入门
    Redis常用数据类型及其对应的底层数据结构
    Java 类加载机制及双亲委派模型
    Java面试高频知识点总结 part3
    Spring框架专题
  • 原文地址:https://www.cnblogs.com/binzi/p/12909660.html
Copyright © 2020-2023  润新知