欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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}");
    }
   }
  }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。