一、场景假设

假设现在有一个泛型类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. jQuery--事件绑定|委派|切换

    一.事件的绑定 1.事件的绑定介绍 事件绑定: bind(type,fn) 给当前对象绑定一个事件.例如:A.bind("click",fn);类似A.click(fn) unbi ...

  2. 解释 AOP 模块?

    AOP 模块用于发给我们的 Spring 应用做面向切面的开发, 很多支持由 AOP 联 盟提供,这样就确保了 Spring 和其他 AOP 框架的共通性.这个模块将元数据编 程引入 Spring.

  3. WEB架构深度优化之PHP

    一.PHP引擎缓存加速优化(4种) 1.eAccelerator 2.XCache 3.APC 4.Zend 二.使用tmpfs作为缓存加速缓存的目录(可用rc.local或fstab来自动挂载) m ...

  4. 学习saltstack (一)

    salt介绍 Salt是一个基础平台管理工具 Salt是一个配置管理系统,能够维护预定义状态的远程节点 Salt是一个分布式远程执行系统,用来在远程节点上执行命令和查询数据 salt的核心功能 是命令 ...

  5. ip地址与子网掩码概述

    IP地址: IP地址(Internet Protocol):IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异. IP地址分为五 ...

  6. html5知识点补充—footer元素的使用

    使用footer元素创建脚注 顾名思义,footer元素通常位于页面的底部.尽管footer通常位于某个区域或者页面的底部,但并非总是如此.footer元素旨在包含作者.网站所有者.版权数据.网站规章 ...

  7. 前端面试题整理——Javascript基础

    常见值类型: let a; //undefined let s = 'abc'; let n = 100; let b = true; let sb = Symbol('s'); let nn = N ...

  8. ubantu系统之 lunch时报错:no such file /....../.lunchrc

    no such file /....../.lunchrc 出现时: 使用 source build/envsetup.sh 执行完后 再用lunch

  9. vue中引入jq

    1.cnpm install jquery2.在webpack.base.conf.js中加入一行代码 const webpack=require("webpack") ----- ...

  10. 【.NET 6】使用EF Core 访问Oracle+Mysql+PostgreSQL并进行简单增改操作与性能比较

     前言 唠嗑一下.都在说去O或者开源,但是对于数据库选型来说,很多人却存在着误区.例如,去O,狭义上讲,是去Oracle数据库.但是从广义上来说,是去Oracle公司产品或者具有漂亮国垄断地位和需要商 ...