C# 通过反射获取类型的字段值及给字段赋值的操作
程序员文章站
2022-04-12 19:03:01
举例:存在一个类:public class student{ public string name; public int age;}student stu1 = new student();现在,我...
举例:
存在一个类:
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}"); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。