目录
五、实际应用1:让日志输出更多信息(反射打印一个实体的所有字段所有内容)
七、实际应用3:使用Invoke关键字通过 Type 类型调用指定的方法
一、获取字段名+字段类型+字段值+设置字段的值
反射,就是遍历实体的PropertyInfo,获取实体的字段的值、特性、类型
【实现的demo】
class Program
{
public class Student
{
public int id { get; set; }
public string name { get; set; }
public int age { get; set; }
}
/// <summary>
/// 通过反射设置实体的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static void SetValueByReflect<T>(T entity, string feildName, object feildValue) where T : class
{
var feild = typeof(T).GetProperty(feildName);
var feildType = feild?.PropertyType;
if (feild != null && feildType != null)
{
var valueToSet = Convert.ChangeType(feildValue, feildType);//输入的值类型转化为实体属性的类型
feild.SetValue(entity, valueToSet);
}
}
static void Main()
{
Student stu = new Student { id = 1, name = "小苏", age = 18 };
//任务一:遍历打印这个实体的字段名,字段类型,字段的值
var propertyList = typeof(Student).GetProperties();
foreach (var fields in propertyList)
{
Console.Write($"字段名: {fields.Name}, ");
Console.Write($"字段类型: {fields.PropertyType.Name}, 字段类型是否为int: {fields.PropertyType == typeof(int)},");
Console.WriteLine($"字段在传入实体stu中对应的值: {fields.GetValue(stu)}");
}
//任务二:获取传入实体stu的age字段,将其age字段值设置为20
SetValueByReflect(stu, "age", 20);
Console.WriteLine($"修改后的age字段值是:{stu.age}");
}
}
输出效果:
字段名: id, 字段类型: Int32, 字段类型是否为int: True,字段在传入实体stu中对应的值: 1
字段名: name, 字段类型: String, 字段类型是否为int: False,字段在传入实体stu中对应的值: 小苏
字段名: age, 字段类型: Int32, 字段类型是否为int: True,字段在传入实体stu中对应的值: 18
修改后的age字段值:20,即20
【方法封装-通过反射设置实体的值】
/// <summary>
/// 通过反射设置实体的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static void SetValueByReflect<T>(T entity, string feildName, object feildValue) where T : class
{
var feild = typeof(T).GetProperty(feildName);
var feildType = feild?.PropertyType;
if (feild != null && feildType != null)
{
var valueToSet = Convert.ChangeType(feildValue, feildType);//输入的值类型转化为实体属性的类型
feild.SetValue(entity, valueToSet);
}
}
二、创建实例并且赋值
Type type = typeof(T);// 获取泛型类型T的Type对象,便于后面使用
string propertyName = "Name";//要修改的属性名称 例如 Name
var csType = type.GetProperty(propertyName).PropertyType;//获取 Name 的属性,例如 string
object instance = Activator.CreateInstance(type);//创建实例,类似于 T instance = new T()
type.GetProperty(propertyName)?.SetValue(instance, Convert.ChangeType("Hello, World!", csType))//赋值,类似于 instance.Name = "Hello, World!".ToString() ChangeType是确保其他类型也可以转化成功
创建实例想调用某个类的方法需要强制转化(例转化为Form类):
form = (Form)Activator.CreateInstance(type);
form.Show();
三、反射的意义
【反射获取字段的意义】灵活获取/设置指定字段的值
四、继承对反射的作用
ABP框架中,一个实体继承Entity对于反射的有什么好处?
public class Entity : Entity<int>
{
[Required]
[Column("id")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override int Id { get; protected set; }
}
好处在于:封装反射方法(例如入参 T)可以写成
where T : Entity
相当于说明了T的实体拥有int id字段,后面可以直接使用这个id字段,而不需要通过反射获取(如果where T : class,想访问id字段还需要其他判断)。
五、实际应用1:让日志输出更多信息(反射打印一个实体的所有字段所有内容)
六、实际应用2:EF的映射Map方法(转移相同字段的数据)
七、实际应用3:使用Invoke关键字通过 Type 类型调用指定的方法
C#高级:使用Invoke关键字通过 Type 类型调用指定的方法-优快云博客