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--------------
----------本篇文章到此結束----------
「其他文章」
- 分享自己平時使用的socket多客戶端通訊的程式碼技術點和軟體使用
- iNeuOS工業網際網路作業系統,增加2154個檢視建模(WEB組態)行業向量圖元、大屏背景及相關圖元
- 多臺雲伺服器的 Kubernetes 叢集搭建
- Elasticsearch學習系列四(聚合搜尋)
- 關於swiper外掛在vue2的使用
- 使用 Abp.Zero 搭建第三方登入模組(一):原理篇
- LVGL庫入門教程 - 顏色和影象
- 物聯網?快來看 Arduino 上雲啦
- SpringBoot JWT Redis 開源知識社群系統
- CVPR2022 | 可精簡域適應
- Spring框架系列(3) - 深入淺出Spring核心之控制反轉(IOC)
- 面試突擊59:一個表中可以有多個自增列嗎?
- CVPR2022 | 弱監督多標籤分類中的損失問題
- JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文帶你釐清箇中曲直,給你個選擇SpringDataJPA的...
- Spring Security:使用者和Spring應用之間的安全屏障
- Mybatisi和Spring整合原始碼分析
- 前端學習 linux —— 第一篇
- call apply bind的作用及區別? 應用場景?
- Bika LIMS 開源LIMS集——實驗室檢驗流程概述及主頁、面板
- 軟體專案管理 7.5.專案進度模型(SPSP)