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

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

(0)

相关推荐

  • 详解C# 反射(Reflection)

    C# 反射(Reflection) 反射指程序可以访问.检测和修改它本身状态或行为的一种能力. 程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象. 您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性. 优缺点 优点: 1.反射提高了程序的灵活性和扩展性. 2.降低耦合性,提高自适应能力. 3.它允许程序创建和控制任何类的对象,无需提前硬编码目标类. 缺点: 1.性能问题:使用反射基本

  • 关于C#反射 你需要知道的

    通常,反射用于动态获取对象的类型.属性和方法等信息.今天带你玩转反射,来汇总一下反射的各种常见操作,捡漏看看有没有你不知道的. 获取类型的成员 Type 类的 GetMembers 方法用来获取该类型的所有成员,包括方法和属性,可通过 BindingFlags 标志来筛选这些成员. using System; using System.Reflection; using System.Linq; public class Program { public static voidMain() {

  • c# 反射+自定义特性保存数据至本地

    最近在项目过程中遇到了保存数据的需求,对实体类的部分数据进行保存,打算采用反射+自定义特性来实现数据保存,利于扩展 1. 采用反射实现能够灵活获取要保存的数据,由于只需要保存实体类(Model)的部分数据,因此采用自定义特性标记需要保存的数据,同时数据要求以.csv格式保存,添加自定义特性有利于对表头进行描述 2. 实现自定义特性 public class ResultAttribute : Attribute { private bool _IsSave; /// <summary> ///

  • C#中字段、属性、只读、构造函数赋值、反射赋值的问题

    C#中字段.属性和构造函数赋值的问题提出问题如下所述: 首先提出几个问题: 1.如何实现自己的注入框架? 2.字段和自动属性的区别是什么? 3.字段和自动属性声明时的直接赋值和构造函数赋值有什么区别? 4.为什么只读字段和只读自动属性(只有get没有set访问器)都可以在构造函数中进行赋值? 5.反射可以给只读字段或者只读属性进行赋值吗? 6.自动属性和普通属性的区别? 这些问题是我在试着写自己的注入实现时遇到的问题.这些问题应该在学习C#时的第一节课就应该学到了,我看网上还有人分享说他在面试时

  • C#基于Linq和反射实现数据持久化框架Xml4DB详解

    我们知道目前大部分的数据库都是关系型数据库, 所谓关系型数据库,就是指建立在关系模型 基础之上的数据库系统,如Oracle.SQL Server.Access.MySQL等.关系模型就是指二维表格模型,因而一个关系型数据库就是由二维表及其之间的联系组成的一个数据组织.一个偶然的机会我接触到了DB4O,它是一个完全面向对象的开源数据库,它的出现完全颠覆了传统的数据库在人们心中的形象,因为传统的数据库需要在数据体.实体之间转换,而且需要映射文件提供映射关系.正是这个项目让我产生了编写Xml4DB的想

  • c#反射机制学习和利用反射获取类型信息

    1..NET可执行应用程序结构 程序代码在编译后生成可执行的应用,我们首先要了解这种可执行应用程序的结构. 应用程序结构分为应用程序域-程序集-模块-类型-成员几个层次,公共语言运行库加载器管理应用程序域,这种管理包括将每个程序集加载到相应的应用程序域以及控制每个程序集中类型层次结构的内存布局. 程序集包含模块,而模块包含类型,类型又包含成员,反射则提供了封装程序集.模块和类型的对象.我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或从现有对象中获取类型,然后调用类型的方法或访问其字段

  • Go语言反射获取类型属性和方法示例

    本系列文章,我将会进一步加深对 Go 语言的讲解,更一步介绍 Go 中的包管理.反射和并发等高级特性. 前面一篇文章主要介绍了 reflect.Type 类型对象.本文将会继续介绍 Go 反射 reflect.StructField 和 reflect.Method 相关的内容. reflect.StructField 和 reflect.Method 如果变量是一个结构体,我们还可以通过结构体域类型对象 reflect.StructField 来获取结构体下字段的类型属性.Type 接口下提供

  • Go语言reflect.TypeOf()和reflect.Type通过反射获取类型信息

    在 Go语言中通过调用 reflect.TypeOf 函数,我们可以从一个任何非接口类型的值创建一个 reflect.Type 值.reflect.Type 值表示着此非接口值的类型.通过此值,我们可以得到很多此非接口类型的信息.当然,我们也可以将一个接口值传递给一个 reflect.TypeOf 函数调用,但是此调用将返回一个表示着此接口值的动态类型的 reflect.Type 值. 实际上,reflect.TypeOf 函数的唯一参数的类型为 interface{},reflect.Type

  • java反射获取一个object属性值代码解析

    有些时候你明明知道这个object里面是什么,但是因为种种原因,你不能将它转化成一个对象,只是想单纯地提取出这个object里的一些东西,这个时候就需要用反射了. 假如你这个类是这样的: private class User { String userName; String userPassword; public String getUserName() { return userName; } public void setUserName(String userName) { this.

  • 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)

  • Golang反射获取变量类型和值的方法详解

    目录 1. 什么是反射 2. reflect.Type 2.1 类型Type和种类Kind 2.2 引用指向元素的类型 2.3 结构体成员类型 3. reflect.Value 3.1 结构体的成员的值 3.2 遍历array.slice 3.3 遍历map 4. 反射的三大定律 4.1 从interface到反射对象 4.2 从反射对象到interface 4.3 通过反射修改对象,该对象值必须是可修改的 1. 什么是反射 反射是程序在运行期间获取变量的类型和值.或者执行变量的方法的能力. G

  • go语言通过反射获取和设置结构体字段值的方法

    本文实例讲述了go语言通过反射获取和设置结构体字段值的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: type MyStruct struct {         N int } n := MyStruct{ 1 } // get immutable := reflect.ValueOf(n) val := immutable.FieldByName("N").Int() fmt.Printf("N=%d\n", val) // prints

  • Java利用反射获取object的属性和值代码示例

    在看反射顺便做个笔记,目前知道的反射的Object都是要有对象的也就是实体Bean. referance:Java反射简易教程 import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 反射处理Bean,得到里面的属性值 * * @author liulinsen * */ publ

  • Java如何通过反射获取私有构造、私有对象、私有字段、私有方法

    Java反射获取私有构造.私有对象.私有字段.私有方法 1. 创建测试的私有对象 /** * @author lirong * @desc 测试对象 * @date 2019/06/20 20:07 */ public class Person { private int age = 5; private String name; private Person(){} private String test(String name){ System.out.println("name: &quo

  • Android获取arrays.xml里的数组字段值实例详解

    Android获取arrays.xml里的数组字段值实例详解 比如在arrays.xml里: <!--leo added for KYLIN-496--> <string-array name="reboot_item"> <item>Reboot</item> <item>Recovery</item> <item>BootLoader</item> </string-array&g

随机推荐