C#随机给一个全部信息都未知的类类型,如何获取该类的类名、属性个数、属性名、属性的数据类型、属性值?

博客 动态
0 160
羽尘
羽尘 2022-05-07 18:58:54
悬赏:0 积分 收藏

C# 随机给一个全部信息都未知的类类型,如何获取该类的类名、属性个数、属性名、属性的数据类型、属性值?

一、场景假设

假设现在有一个泛型类T的实例对象t,该T类的全部信息都未知。

要求:打印输出实例对象t的类名、属性个数、属性名、属性的数据类型、属性值。

二、解决问题

1、我们根据输出的内容要求定义一个实体类如下:

    public class GeneralDataModel    {        /// <summary>        /// 类名        /// </summary>        public string class_name { get; set; }        /// <summary>        /// 属性个数        /// </summary>        public int prop_count { get; set; }        /// <summary>        /// 单个属性的信息        /// </summary>        public List<PropInfoItem> props { get; set; }    }    public class PropInfoItem    {        /// <summary>        /// 属性名        /// </summary>        public string prop_name { get; set; }        /// <summary>        /// 属性数据类型        /// </summary>        public string prop_data_type { get; set; }        /// <summary>        /// 属性值        /// </summary>        public string prop_value { get; set; }    }

2、编写一个方法,该方法的主要功能是解析实例对象t,并输出步骤1中格式的内容。方法代码实现如下:

        public static GeneralDataModel DataAnalysis<T>(T t)        {            var data_type = t.GetType();            var propInfo = data_type.GetProperties();            var list = new List<PropInfoItem>();            foreach (var item in propInfo)            {                var e = new PropInfoItem                {                    prop_name = item.Name,                    prop_data_type = item.PropertyType.Name,                    prop_value = item.GetValue(t) == null ? "" : item.GetValue(t).ToString()                };                list.Add(e);            }            var res = new GeneralDataModel            {                class_name = data_type.Name,                prop_count = propInfo.Count(),                props = list            };            return res;        }

三、验证方法功能

1、假设现在有一个学生类如下所示:

    public class Student    {        /// <summary>        /// 学号        /// </summary>        public int no { get; set; }        /// <summary>        /// 姓名        /// </summary>        public string name { get; set; }        /// <summary>        /// 年级        /// </summary>        public string grade { get; set; }        /// <summary>        /// 出生年月        /// </summary>        public DateTime birth { get; set; }    }

2、根据该类实例化了一个st对象如下:

   var st = new Student()   {       no = 123456,       name = "张三",       grade = "六年级",       birth = DateTime.Now    };

3、调用DataAnalysis方法解析st,并打印输出结果:

   var res = DataAnalysis(st);    Console.WriteLine(JsonConvert.SerializeObject(res));

4、输出结果如下:

{    "class_name": "Student",    "prop_count": 4,    "props": [        {            "prop_name": "no",            "prop_data_type": "Int32",            "prop_value": "123456"        },        {            "prop_name": "name",            "prop_data_type": "String",            "prop_value": "张三"        },        {            "prop_name": "grade",            "prop_data_type": "String",            "prop_value": "六年级"        },        {            "prop_name": "birth",            "prop_data_type": "DateTime",            "prop_value": "2022/5/7 17:21:12"        }    ]}

5、看到输出结果后,感觉完美的解决了问题。

四、变化无常

1、因为种种原因,学生类增加了两个属性,同时实例化对象的创建形式也变了,变化后的形式如下:

    public class Student    {        public Student()        {        }        public Student(string id_card_no, string address)        {            this.id_card_no = id_card_no;            this.address = address;        }        /// <summary>        /// 学号        /// </summary>        public int no { get; set; }        /// <summary>        /// 姓名        /// </summary>        public string name { get; set; }        /// <summary>        /// 年级        /// </summary>        public string grade { get; set; }        /// <summary>        /// 出生年月        /// </summary>        public DateTime birth { get; set; }        /// <summary>        /// 身份证(受保护类型)        /// </summary>        protected string id_card_no { get; set; }        /// <summary>        /// 家庭地址(私有类型)        /// </summary>        private string address { get; set; }    }
   var st = new Student("777888202005071111", "家庭地址私有,暂时不方便透露")   {       no = 123456,       name = "张三",       grade = "六年级",       birth = DateTime.Now   };

2、再次调用DataAnalysis方法解析st,并打印输出结果:

   var res = DataAnalysis(st);   Console.WriteLine(JsonConvert.SerializeObject(res));

3、输出结果如下:

{    "class_name": "Student",    "prop_count": 4,    "props": [        {            "prop_name": "no",            "prop_data_type": "Int32",            "prop_value": "123456"        },        {            "prop_name": "name",            "prop_data_type": "String",            "prop_value": "张三"        },        {            "prop_name": "grade",            "prop_data_type": "String",            "prop_value": "六年级"        },        {            "prop_name": "birth",            "prop_data_type": "DateTime",            "prop_value": "2022/5/7 17:40:21"        }    ]}

4、看到输出结果时,咦?怎么似乎好像哪里不对?新增的两个属性怎么没有被解析并输出呢?

五、反射了解一下?

1、通过种种途径或者查阅其他资料你了解到了反射的相关知识,并找到了一个名为GetRuntimeProperties的方法。

2、修改原先的解析方法代码如下:

    public static GeneralDataModel DataAnalysis<T>(T t)    {        var data_type = t.GetType();        var refPropInfo = data_type.GetRuntimeProperties();        var list = new List<PropInfoItem>();        foreach (var item in refPropInfo)        {            var e = new PropInfoItem            {                prop_name = item.Name,                prop_data_type = item.PropertyType.Name,                prop_value = item.GetValue(t) == null ? "" : item.GetValue(t).ToString()            };            list.Add(e);        }        var res = new GeneralDataModel        {            class_name = data_type.Name,            prop_count = refPropInfo.Count(),            props = list        };        return res;    }

3、再一次调用DataAnalysis方法解析st,并打印输出结果:

   var res = DataAnalysis(st);   Console.WriteLine(JsonConvert.SerializeObject(res));

 4、输出结果如下:

{    "class_name": "Student",    "prop_count": 6,    "props": [        {            "prop_name": "no",            "prop_data_type": "Int32",            "prop_value": "123456"        },        {            "prop_name": "name",            "prop_data_type": "String",            "prop_value": "张三"        },        {            "prop_name": "grade",            "prop_data_type": "String",            "prop_value": "六年级"        },        {            "prop_name": "birth",            "prop_data_type": "DateTime",            "prop_value": "2022/5/7 17:52:12"        },        {            "prop_name": "id_card_no",            "prop_data_type": "String",            "prop_value": "777888202005071111"        },        {            "prop_name": "address",            "prop_data_type": "String",            "prop_value": "家庭地址暂时不方便透露"        }    ]}

5、看到这输出结果,脸上露出了满意的笑容,啊~~~问题终于解决了,开森^_^

六、前后对比并溯源

1、方法前后变化仅仅只有一处,由GetProperties变为了GetRuntimeProperties

2、溯源发现:

  • GetProperties:在System命名空间下,是Type类的实例方法。
  • GetRuntimeProperties(Type类的扩展方法):在System.Reflection命名空间下,是RuntimeReflectionExtensions类的静态方法。

--------------The  End--------------

----------本篇文章到此结束----------

posted @ 2022-05-07 18:07 张欧昊辰 阅读(27) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员