一、场景假设

假设现在有一个泛型类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--------------

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

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

  1. PHP处理上传文件信息数组中的文件类型 正确获取

    PHP处理上传文件信息数组中的文件类型$_FILES['type']由客户端浏览器提供,有可能是黑客伪造的信息,请写一个函数来确保用户上传的图像文件类型真实可靠 如果是一般文件则通过 mime_con ...

  2. 逆向分析objc,所有类的信息都能在动态调试中获取。

    因为objc是动态绑定的,程序运行时必须知道如何绑定,依靠的就是类描述.只要知道类描述是如何组织的就可以获取一切有用的信息.不知道是幸运还是不幸,这些信息全部都在运行的程序中.即使没有IDA这样的工具 ...

  3. 反射01 Class类的使用、动态加载类、类类型说明、获取类的信息

    0 Java反射机制 反射(Reflection)是 Java 的高级特性之一,是框架实现的基础. 0.1 定义 Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对 ...

  4. 深刻:截获windows的消息并分析实例(DefWindowProc),以WM_NCHITTEST举例(Windows下每一个鼠标消息都是由 WM_NCHITTEST 消息产生的,这个消息的参数包含了鼠标位置的信息)

    1,回调函数工作机制 回调函数由操作系统自动调用,回调函数的返回值当然也是返回给操作系统了. 2,截获操作系统发出的消息,截获到后,将另外一个消息返回给操作系统,已达到欺骗操作系统的目的. 下面还是以 ...

  5. python3 - 商品管理的程序,商品信息都存在一个json串里面

    商品管理的程序,商品信息都存在一个json串里面 1.查询商品信息 #校验商品是否存在 2.新增商品 # #校验商品是否存在 #校验价格是否合法 3.修改商品信息 ##校验商品是否存在 if chic ...

  6. 每一个web开发者都应该了解的HTTP/2

    我认为每一个 web 开发者都应该对这个支撑了整个 Web 世界的 HTTP 协议有所了解,这样才能帮助你更好的完成开发任务.在这篇文章中,我将讨论什么是 HTTP,它是怎么产生的,它的地位,以及我们 ...

  7. 利用Python完成一个小游戏:随机挑选一个单词,并对其进行乱序,玩家要猜出原始单词

    一 Python的概述以及游戏的内容 Python是一种功能强大且易于使用的编程语言,更接近人类语言,以至于人们都说它是“以思考的速度编程”:Python具备现代编程语言所应具备的一切功能:Pytho ...

  8. 从SQLite获取数据完成一个产品信息展示

    在ios实际开发当中,我们常常用到Core Data做为数据储存首选.但在处理一些大量复杂的数据值且数据之间相互关联的时候,这就不得不使用关系型数据库来实现.例如一个导航程序,自身应该包含大量的地图自 ...

  9. 61. 从1到n,共有n个数字,每个数字只出现一次。从中随机拿走一个数字x,请给出最快的方法,找到这个数字。如果随机拿走k(k>=2)个数字呢?[find k missing numbers from 1 to n]

    [本文链接] http://www.cnblogs.com/hellogiser/p/find-k-missing-numbers-from-1-to-n.html  [题目] 从1到n,共有n个数字 ...

随机推荐

  1. screen--后台不挂断运行

    方法一:1.进入项目目录下,运行下面程序:nohup python manage.py runserver 0.0.0.0:5008 &nohup(no hang up)用途:不挂断的运行命令 ...

  2. 学习openstack(六)

    VIII openstack(1) 传统的数据中心面临的问题:成本.效率(要快).管理方面(物理机.云主机): 云计算:对运维需求总体量是减少了,尤其是硬件工程师,对运维的技术要求提高了: 云计算是个 ...

  3. 实验配置cisco单臂路由

    第一步 搭建实验拓扑图 第二步 对路由器做基本配置 为路由器创建名称: 设置进入特权模式 口令:控制台登录密码:vty登录密码 禁用DNS查找: 加密明文密码: 创建一个向访问设备者发出警告的标语&q ...

  4. 动态规划 洛谷P1048 [NOIP2005 普及组] 采药

    洛谷P1048 [NOIP2005 普及组] 采药 洛谷的一个谱架-的题目,考的是01背包问题,接下来分享一下我的题解代码. AC通过图: 我的代码: 1 //动态规划 洛谷P1048 [NOIP20 ...

  5. Leetcode刷题之矩阵中的指针用法

    矩阵中的指针用法 1 快慢指针 ​ Leetcode27移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度.不要使用额外的数组 ...

  6. vulnhub靶机Tr0ll:1渗透笔记

    Tr0ll:1渗透笔记 靶场下载地址:https://www.vulnhub.com/entry/tr0ll-1,100/ kali ip:192.168.20.128 靶机和kali位于同一网段 信 ...

  7. Numpy非常重要有用的数组合并操作

    Numpy非常重要有用的数组合并操作 背景:在给机器学习准备数据的过程中,经常需要进行不同来源的数据合并的操作. 两类场景: 给已有的数据添加多行,比如增添一些样本数据进去: 给已有的数据添加多列,比 ...

  8. 好用开源的C#快速开发平台

    NFine 是基于 C# 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展,让Web开发更迅速.简单.NFine是一套基于 ASP.NET ...

  9. 百度开放云 BOS Uploader

    百度开放云 BOS Uploader bce-bos-uploader 是基于 bce-sdk-js 开发的一个 ui 组件,易用性更好.DEMO地址是:http://leeight.github.i ...

  10. java中程序,进程和线程的区别

    2.程序,进程和线程的区别 马克-to-win:程序,进程和线程的区别是什么?这个问题比较抽象难理解,但又非常重要.我并不想给出一大堆抽象的学术解释,那样只能误国误民.所以我先给大家举一个例子.马克- ...