C# 通過反射獲取類型的字段值及給字段賦值的操作
舉例:
存在一個類:
Public Class Student { public string name; public int age; } Student stu1 = new Student();
現在,我們想通過反射在運行時給stu1的name 和 age字段 賦值,讓name = “小明”,age = 15,怎麼做?
簡單的代碼如下:
...略 using System.Reflection;//反射類 ...略 static void Main(string[] args) { Type t = stu1.GetType(); FieldInfo filedInfo1 = t.GetField(”name"); FieldInfo filedInfo2 = t.GetField(”age"); fieldInfo1.SetValue(stu1,"小明"); fieldInfo2.SetValue(stu1,15); }
需要註意的是:FieldInfo的SetValue方法有可能會導致異常,比如 fieldInfo2.SetValue(stu1,“15”),這句話給一個int型字段賦瞭string類型的值,編譯是不會報錯的,在運行時會拋出一個System.ArgumentException異常,請多加註意.
有瞭以上的瞭解,讓我們寫一個簡單的動態字段賦值/取值類Dynamic
具體代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace MyUnityHelper { /// <summary> /// 動態編譯類 /// </summary> public class Dynamic { /// <summary> /// 動態賦值 /// </summary> /// <param name="obj"></param> /// <param name="fieldName"></param> /// <param name="value"></param> public static void SetValue(object obj,string fieldName,object value) { FieldInfo info = obj.GetType().GetField(fieldName); info.SetValue(obj, value); } /// <summary> /// 泛型動態賦值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <param name="fieldName"></param> /// <param name="value"></param> public static void SetValue<T>(object obj, string fieldName, T value) { FieldInfo info = obj.GetType().GetField(fieldName); info.SetValue(obj, value); } /// <summary> /// 動態取值 /// </summary> /// <param name="obj"></param> /// <param name="fieldName"></param> /// <returns></returns> public static object GetValue(object obj, string fieldName) { FieldInfo info = obj.GetType().GetField(fieldName); return info.GetValue(obj); } /// <summary> /// 動態取值泛型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <param name="fieldName"></param> /// <returns></returns> public static T GetValue<T>(object obj,string fieldName) { FieldInfo info = obj.GetType().GetField(fieldName); return (T)info.GetValue(obj); } } }
補充:C#利用反射方法實現對象的字段和屬性之間值傳遞
在面向對象開發過程中,往往會遇到兩個對象之間進行值傳遞的情況,如果對象中的屬性和字段較多,手動一一賦值效率實在太低。
這裡就整理瞭一個通用的對象之間進行值傳遞的方法,並且考慮到對象中可能包含類屬性,因此還用到瞭遞歸以解決這個問題。
下面上代碼:
public static void ConvertObject(object SrcClass, object DesClass, bool convertProperty = true, bool convertField = true, bool showError = true) { try { if (SrcClass == null) { return; } if (convertProperty) { PropertyInfo[] srcProperties = SrcClass.GetType().GetProperties(); PropertyInfo[] desProperties = DesClass.GetType().GetProperties(); if (srcProperties.Length > 0 && desProperties.Length > 0) { foreach (var srcPi in srcProperties) { foreach (var desPi in desProperties) { if (srcPi.Name == desPi.Name && srcPi.PropertyType == desPi.PropertyType && desPi.CanWrite) { if (srcPi.PropertyType.IsClass) { ConvertObject(srcPi.GetValue(SrcClass, null), desPi.GetValue(DesClass, null), convertProperty, convertField, showError); } else { Object value = srcPi.GetValue(SrcClass, null); desPi.SetValue(DesClass, value, null); } } } } } } if (convertField) { FieldInfo[] srcFields = SrcClass.GetType().GetFields(); FieldInfo[] desFields = DesClass.GetType().GetFields(); if (srcFields.Length > 0 && desFields.Length > 0) { foreach (var srcField in srcFields) { foreach (var desField in desFields) { if (srcField.Name == desField.Name && srcField.FieldType == desField.FieldType) { if (srcField.FieldType.IsClass) { ConvertObject(srcField.GetValue(SrcClass), desField.GetValue(DesClass), convertProperty, convertField, showError); } else { Object value = srcField.GetValue(SrcClass); desField.SetValue(DesClass, value); } } } } } } } catch (Exception ex) { if (showError) { MessageBox.Show($"Convert Error: Method={nameof(ConvertObject)}, Message={ex.Message}"); } else { throw new Exception($"Convert Error: Method={nameof(ConvertObject)}, Message={ex.Message}"); } } }
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。