Unity —— 反射

目录

一、反射

[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()
    {
        
    }
}
相关推荐
初心未改HD1 小时前
Go Modules:依赖管理的完全指南
开发语言·golang
楼田莉子1 小时前
仿照Muduo的高并发服务器:EventLoop模块及与TimeWheel模块联调
java·开发语言
小雅痞1 小时前
[Java][Leetcode middle] 3. 无重复字符的最长子串
java·开发语言·leetcode
SamDeepThinking1 小时前
为什么你做技术方案总是漏掉边界情况
java·后端·程序员
逻辑驱动的ken2 小时前
Java高频面试考点场景题21
java·开发语言·面试·职场和发展·求职招聘
rOuN STAT2 小时前
Golang 构建学习
开发语言·学习·golang
番茄去哪了2 小时前
单体转微服务:正确的拆分思路与实战原则(上)
java·微服务·架构
AI进化营-智能译站2 小时前
ROS2 C++开发系列19-枚举定义机器人状态机|随机数生成仿真测试数据流
java·c++·ai·机器人
fengxin_rou2 小时前
黑马点评项目万字总结:从redis基础到实战应用详解
java·开发语言·分布式·后端·黑马点评