目录
[1.1 什么是反射](#1.1 什么是反射)
[1.2 反射常用的类](#1.2 反射常用的类)
[1.3 反射常用的命名空间](#1.3 反射常用的命名空间)
[二、Type 类](#二、Type 类)
[三、Assembly 类](#三、Assembly 类)
[四、Activator 类](#四、Activator 类)
一、反射
1.1 什么是反射
程序在运行时,动态地查看、获取、创建、调用某个类型的信息。
1.2 反射常用的类
|-------------------|-----------------------------------------|
| Type | 表示一个类型的信息 |
| Assembly | 表示程序集,可以查找程序集中的类 |
| Activator | 根据 Type 动态创建对象 |
| FieldInfo | 表示字段信息 |
| PropertyInfo | 表示属性信息 |
| MethodInfo | 表示方法信息 |
| ConstructorInfo | 表示构造函数信息 |
| BindingFlags | 控制查找 public、private、static、instance 等成员 |
1.3 反射常用的命名空间
using System; // 提供 Type、Activator
using System.Reflection; // 提供 Assembly、FieldInfo、PropertyInfo、MethodInfo 等
二、Type 类
Type 是反射中最核心的类,它表示一个类型(eg:int、Player、Monster、List<int>、GameObject、Transform、自定义脚本类等)的信息。
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player
{
public string name = "张三";
public int hp = 100;
private int money = 999;
public void Attack()
{
Console.WriteLine("玩家攻击");
}
public void Skill(string skillName)
{
Console.WriteLine("释放技能:" + skillName);
}
private void Secret()
{
Console.WriteLine("隐藏方法");
}
public string Name { get; set; }
public int Hp { get; set; }
}
public class Lesson22 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 获取 Type(重要)
Type type = typeof(Player);
// 1.获取类名、命名空间、程序集信息等
print(type.Name);
print(type.FullName);
print(type.Namespace);
print(type.Assembly);
// 2.字段相关
// 2.1 获取 public 字段(类)
FieldInfo field1 = type.GetField("hp");
print(field1.Name); // hp
// 2.2 获取 private 字段(类)
// BindingFlags.NonPublic 表示 非 public 成员。
// BindingFlags.Instance 表示 非 static 成员。
FieldInfo field2 = type.GetField("money", BindingFlags.NonPublic | BindingFlags.Instance);
print(field2.Name); // money
// 2.3 读取字段的值
Player player1 = new Player();
print(field1.GetValue(player1)); // 100
// 2.4 修改字段的值
field1.SetValue(player1, 200);
print(field1.GetValue(player1)); // 200
print(player1.hp); // 200
// 3.方法相关
// 3.1 获取 public 方法(类)
MethodInfo method1 = type.GetMethod("Attack");
print(method1.Name); // Attack
// 3.2 获取 private 方法(类)
// 略
// 3.3 调用无参方法
method1.Invoke(player1, null); // 等价于 player1.Attack()
// 3.4 调用有参方法
MethodInfo method2 = type.GetMethod("Skill");
method2.Invoke(player1, new object[] {"火球术"}); // 等价于 player1.Skill("火球术")
// 4.属性相关(本质上是方法的封装)
// 4.1 获取属性
// 略
// 4.2 读取属性
player1.Name = "张三";
player1.Hp = 100;
PropertyInfo property = type.GetProperty("Name");
print(property.GetValue(player1));
// 4.3 修改属性
property.SetValue(player1, "李四");
print(property.GetValue(player1));
}
// Update is called once per frame
void Update()
{
}
}
补充知识点:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using UnityEngine;
public class Animal
{
}
public class Dog : Animal
{
}
public class Lesson22 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 1.type1.IsAssignableFrom(type2):type2 类型的对象,能不能赋值给 type1 类型的变量。
// 常用于:type2 是不是 type1 的子类、某个类(type2)有没有实现某个接口(type1)、某个 Unity 脚本(type2)能不能作为 MonoBehaviour 组件(type1)
if (typeof(Animal).IsAssignableFrom(typeof(Dog)))
{
Animal animal = Activator.CreateInstance(typeof(Dog)) as Animal;
}
// 2.通过反射获取泛型类型里面的泛型参数类型
List<string> list = new List<string>();
Type listType = typeof(List<string>);
// Type listType = list.GetType(); // 获取 type 的另一种方法
Type[] types = listType.GetGenericArguments();
print(types[0]);
}
// Update is called once per frame
void Update()
{
}
}
三、Assembly 类
Assembly 可以理解为程序集(C# 代码编译后形成的代码包)。在 Unity 项目运行时,底层有很多程序集,如 Assembly-CSharp、UnityEngine.CoreModule、UnityEngine.UI 等。
其中 Assembly-CSharp 是 Unity 默认给你项目脚本生成的程序集。
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson22 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 1.获取当前程序集
Assembly assembly = Assembly.GetExecutingAssembly();
print(assembly.FullName);
// 2.获取程序集中所有类型
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{
print(t.FullName); // 打印当前程序集中的所有类
}
// 获取程序集中某个类
Type type = assembly.GetType("Lesson1");
print(type.FullName);
}
// Update is called once per frame
void Update()
{
}
}
四、Activator 类
Activator 用来动态创建对象。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using UnityEngine;
public class Monster1
{
public string name = "史莱姆";
public void Show()
{
Console.WriteLine("怪物名字:" + name);
}
}
public class Monster2
{
public string name;
public int hp;
public Monster2(string name, int hp)
{
this.name = name;
this.hp = hp;
}
public void Show()
{
Console.WriteLine(name + ",血量:" + hp);
}
}
public class Lesson22 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 创建无参构造对象
Type type1 = typeof(Monster1);
object obj1 = Activator.CreateInstance(type1);
Monster1 monster1 = obj1 as Monster1;
monster1.Show();
// 创建有参构造对象
Type type2 = typeof(Monster2);
object obj2 = Activator.CreateInstance(type2, "哥布林", 300);
Monster2 monster2 = obj2 as Monster2;
monster2.Show();
}
// Update is called once per frame
void Update()
{
}
}