Unity C# 游戏开发 反射 Reflection 案例讲解(图文详细,带源码)

33 篇文章 5 订阅
17 篇文章 0 订阅

今天打球的小姐姐格外。。。

小姐姐为了感谢我最近的付出,邀请我一块打球,那我必须得把把赢她(钢铁直男的气势不能丢),不能给程序员丢脸,我被眼前的球晃的好晕🙈,很快小姐姐也没力气了,坐在了地上,说最近被反射搞得好迷糊🙈。
请添加图片描述
那我肯定不能惯着她😎,反射下,看小姐姐的脚本里都写了啥!!😎😎😎💛😻😻



🔥总目录C#语法系列详解——总目录持续更新中。。。

一、反射是什么?

我们先来个官方的解释:这是官方的文档文档链接

反射提供了描述程序集、模块和类型的对象(类型为Type)。您可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果您在代码中使用属性,反射使您能够访问它们。

讲完之后,小姐姐的状态是这样的:
请添加图片描述
相信大家也有这种感觉,这都说的是啥?
用我自己的理解来解释:反射可以让你知道一个程序集里面的构造函数,字段,属性,方法,等等。知道了这些,你就可以去创建相应的对象了。
接下来就用我偷偷从小姐姐那拷过来的脚本来练练手。


二、反射怎么用?

我们直接用小姐姐的脚本来一块学习下

1.要反射的目标脚本内容

下面就是小姐姐脚本的全部内容,里面有字段,属性,构造函数,方法,我们可以先不看里面写的啥,一会用反射就都可以看到啦!😜

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReflectionTest
{
    /// <summary>
    /// 排名
    /// </summary>
    public int ranking;
    /// <summary>
    /// 名字
    /// </summary>
    private string m_name;
    /// <summary>
    /// 长度
    /// </summary>
    private string m_length;
    /// <summary>
    /// 形状
    /// </summary>
    private string m_shape;

    #region 构造函数
    public ReflectionTest(string name, string length)
    {
        this.m_name = name;
        this.m_length = length;
    }
    public ReflectionTest(string name,string shape, string length)
    {
        this.m_name = name;
        this.m_shape = shape;
        this.m_length = length;
    }

    public ReflectionTest(string shape)
    {
        this.m_shape = shape;
    }

    public ReflectionTest()
    {
        
    }

    #endregion
   
    #region 属性

    /// <summary>
    /// 名字
    /// </summary>
    public string Name
    {
        get => m_name;
        set => m_name = value;
    }

    /// <summary>
    /// 长度
    /// </summary>
    public string Length
    {
        get => m_length;
        set => m_length = value;
    }

    /// <summary>
    /// 形状
    /// </summary>
    public string Shape
    {
        get => m_shape;
        set => m_shape = value;
    }

    #endregion
    
    /// <summary>
    /// 信息打印出来
    /// </summary>
    public void ShowContent()
    {
        Debug.Log("姓名:" + m_name + "\n" + "形状:" + m_shape + "---" + "长度:" + m_length);
    }
    /// <summary>
    /// 打印排名
    /// </summary>
    public void ShowRanking()
    {
        Debug.Log("排名是:"+ranking);
    }
    /// <summary>
    /// 要开始发动啦!!
    /// </summary>
    public void StartMove()
    {
        Debug.Log(m_name+"要开始发动啦!!");
    }
}

💥💥接下来就让我们大展身手

2.反射的实际应用

我就举几个比较常用的方法,抛砖引玉

感兴趣的小伙伴可以根据官方文档去做更多的实践。要永远相信,官方文档是最全面的,文档链接在上面发了。
首先我们创建个脚本,挂载到空物体上
在这里插入图片描述

在脚本中实例化要反射的小姐姐脚本。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;

/// <summary>
/// 反射的相关测试
/// </summary>
public class FindOfReflection : MonoBehaviour
{
    private ReflectionTest reflectionTest;

    private void Awake()
    {
        reflectionTest = new ReflectionTest();
    }
}

1).获取构造函数的所有参数及参数的数据类型

private void Start()
    {
         SeeConstructor();
    }
 /// <summary>
    /// 获取构造函数的所有参数及参数的数据类型
    /// </summary>
    private void SeeConstructor()
    {
        //获取reflectionTest的Type
        Type type = reflectionTest.GetType();
        //通过Type获取这个类的所有构造函数信息
        ConstructorInfo[] constructorArray = type.GetConstructors();
        foreach (ConstructorInfo constructorInfo in constructorArray)
        {
            //获取每个构造函数的所有参数
            ParameterInfo[] parameterArray = constructorInfo.GetParameters();
            foreach (ParameterInfo parameterInfo in parameterArray)
            {
                Debug.Log("数据类型:"+parameterInfo.ParameterType.ToString()+"\n"+"参数名字:"+parameterInfo.Name);
            }
        }
    }

🌵执行结果如下
在这里插入图片描述

2).通过反射获取属性

 private void Start()
    {
         SeeProperty();
    }
 /// <summary>
    /// 通过反射获取属性
    /// </summary>
    private void SeeProperty()
    {
        //获取reflectionTest的Type
        Type type = reflectionTest.GetType();
        //获取所有属性信息
        PropertyInfo[] propertyInfos = type.GetProperties();
        foreach (PropertyInfo propertyInfo in propertyInfos)
        {
            //打印出来属性的名字
            Debug.Log("属性:"+propertyInfo.Name);
        }
    }

🌵执行结果如下
在这里插入图片描述

3).查看类中的公开方法

 private void Start()
    {
         SeePublicMethod();
    }
      /// <summary>
    /// 查看类中的公开方法
    /// </summary>
    private void SeePublicMethod()
    {
        Type type = reflectionTest.GetType();
        //通过type获取所有公开方法的信息
        MethodInfo[] methodInfos = type.GetMethods();
        foreach (MethodInfo methodInfo in methodInfos)
        {
            Debug.Log("公开方法的返回类型:"+methodInfo.ReturnType+"---"+"方法的名字:"+methodInfo.Name);
        }
    }

🌵执行结果如下
在这里插入图片描述

4).查看类中的公开字段

 private void Start()
    {
         SeePublicField();
    }
     /// <summary>
    /// 查看类中的公开字段
    /// </summary>
    private void SeePublicField()
    {
        Type type = reflectionTest.GetType();
        //通过type获取所有公开的字段的信息
        FieldInfo[] fieldInfos = type.GetFields();
        foreach (FieldInfo fieldInfo in fieldInfos)
        {
            Debug.Log("公开的字段的名字:"+fieldInfo.Name);
        }
    }

🌵执行结果如下
在这里插入图片描述
中断一下,我感觉这小姐姐的脚本不对劲,你们回头看下反射出来的数据,难道。。😱

5).通过反射用构造函数动态生成对象

那我们就将计就计,生成几个符合小姐姐的对象吧

 private void Start()
    {
         CreatObjectByConstruct();
    }
     /// <summary>
    /// 通过反射用构造函数动态生成对象
    /// </summary>
    private void CreatObjectByConstruct()
    {
        Type type = reflectionTest.GetType();
        Type[] typeArray ={typeof(string), typeof(string),typeof(string)};
        //根据构造函数参数类型来获取构造函数
        ConstructorInfo constructorInfo = type.GetConstructor(typeArray);
        //要传入的参数
        object[] objectArray={"王二","蘑菇","8cm"};
        //调用构造函数来生成对象
        object obj = constructorInfo.Invoke(objectArray);
        //调用打印方法,看是否有输出
        ((ReflectionTest)obj).ShowContent();
    }

🌵执行结果如下
在这里插入图片描述

6).通过反射用Activator静态生成对象

再来一个!

 private void Start()
    {
         CreatObjByActivator();
    }
     /// <summary>
    /// 通过反射用Activator静态生成对象
    /// </summary>
    private void CreatObjByActivator()
    {
        Type type = reflectionTest.GetType();
        object[] objects = {"张三","阿姆斯特朗回旋炮", "22cm"};
        object obj = Activator.CreateInstance(type, objects);
        //调用打印方法,看是否有输出
        ((ReflectionTest)obj).ShowContent();
    }

🌵执行结果如下
在这里插入图片描述
❓❓到这里有的C友肯定要说,不懂就问,什么是阿姆斯特朗回旋炮啊?❓❓

就是这货
请添加图片描述

7).通过反射,创建对象,给字段,属性赋值,调用方法

最后我们再来生成对象并修改相应的内容吧

private void Start()
    {
         CreatAndSet();
    }
     /// <summary>
    /// 通过反射,创建对象,给字段,属性赋值,调用方法
    /// </summary>
    private void CreatAndSet()
    {
        Type type = reflectionTest.GetType();
        //创建对象
        object obj = Activator.CreateInstance(type);
        //通过名字获取字段
        FieldInfo fieldInfo = type.GetField("ranking");
        //给字段赋值
        fieldInfo.SetValue(obj,1);
        //获取所有属性的信息
        PropertyInfo[] propertyInfos = type.GetProperties();
        string[] strings ={"李四", "阿姆斯特朗回旋炮", "33cm"};
        //依次给属性属性赋值
        for (int i = 0; i < propertyInfos.Length; i++)
        {
            propertyInfos[i].SetValue(obj,strings[i],null);
        }
        //根据名字找到方法的信息
        MethodInfo methodInfo = type.GetMethod("StartMove");
        //执行方法
        methodInfo.Invoke(obj, null);
        //根据名字找到方法的信息
        MethodInfo methodInfo2 = type.GetMethod("ShowRanking");
        //执行方法
        methodInfo2.Invoke(obj, null);
    }

🌵执行结果如下
在这里插入图片描述

三、源码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;

/// <summary>
/// 反射的相关测试
/// </summary>
public class FindOfReflection : MonoBehaviour
{
    private ReflectionTest reflectionTest;

    private void Awake()
    {
        reflectionTest = new ReflectionTest();
    }

    private void Start()
    {
        SeeConstructor();
        SeeProperty();
        SeePublicMethod();
        SeePublicField();
        CreatObjectByConstruct();
        CreatObjByActivator();
        CreatAndSet();
    }

    /// <summary>
    /// 获取构造函数的所有参数及参数的数据类型
    /// </summary>
    private void SeeConstructor()
    {
        //获取reflectionTest的Type
        Type type = reflectionTest.GetType();
        //通过Type获取这个类的所有构造函数信息
        ConstructorInfo[] constructorArray = type.GetConstructors();
        foreach (ConstructorInfo constructorInfo in constructorArray)
        {
            //获取每个构造函数的所有参数
            ParameterInfo[] parameterArray = constructorInfo.GetParameters();
            foreach (ParameterInfo parameterInfo in parameterArray)
            {
                Debug.Log("数据类型:" + parameterInfo.ParameterType.ToString() + "\n" + "参数名字:" + parameterInfo.Name);
            }
        }
    }

    /// <summary>
    /// 通过反射获取属性
    /// </summary>
    private void SeeProperty()
    {
        //获取reflectionTest的Type
        Type type = reflectionTest.GetType();
        //获取所有属性信息
        PropertyInfo[] propertyInfos = type.GetProperties();
        foreach (PropertyInfo propertyInfo in propertyInfos)
        {
            //打印出来属性的名字
            Debug.Log("属性:" + propertyInfo.Name);
        }
    }

    /// <summary>
    /// 查看类中的公开方法
    /// </summary>
    private void SeePublicMethod()
    {
        Type type = reflectionTest.GetType();
        //通过type获取所有公开方法的信息
        MethodInfo[] methodInfos = type.GetMethods();
        foreach (MethodInfo methodInfo in methodInfos)
        {
            Debug.Log("公开方法的返回类型:" + methodInfo.ReturnType + "---" + "方法的名字:" + methodInfo.Name);
        }
    }

    /// <summary>
    /// 查看类中的公开字段
    /// </summary>
    private void SeePublicField()
    {
        Type type = reflectionTest.GetType();
        //通过type获取所有公开的字段的信息
        FieldInfo[] fieldInfos = type.GetFields();
        foreach (FieldInfo fieldInfo in fieldInfos)
        {
            Debug.Log("公开的字段的名字:" + fieldInfo.Name);
        }
    }


    /// <summary>
    /// 通过反射用构造函数动态生成对象
    /// </summary>
    private void CreatObjectByConstruct()
    {
        Type type = reflectionTest.GetType();
        Type[] typeArray = {typeof(string), typeof(string), typeof(string)};
        //根据构造函数参数类型来获取构造函数
        ConstructorInfo constructorInfo = type.GetConstructor(typeArray);
        //要传入的参数
        object[] objectArray = {"王二", "蘑菇", "8cm"};
        //调用构造函数来生成对象
        object obj = constructorInfo.Invoke(objectArray);
        //调用打印方法,看是否有输出
        ((ReflectionTest) obj).ShowContent();
    }

    /// <summary>
    /// 通过反射用Activator静态生成对象
    /// </summary>
    private void CreatObjByActivator()
    {
        Type type = reflectionTest.GetType();
        object[] objects = {"张三", "阿姆斯特朗回旋炮", "22cm"};
        object obj = Activator.CreateInstance(type, objects);
        //调用打印方法,看是否有输出
        ((ReflectionTest) obj).ShowContent();
    }

    /// <summary>
    /// 通过反射,创建对象,给字段,属性赋值,调用方法
    /// </summary>
    private void CreatAndSet()
    {
        Type type = reflectionTest.GetType();
        //创建对象
        object obj = Activator.CreateInstance(type);
        //通过名字获取字段
        FieldInfo fieldInfo = type.GetField("ranking");
        //给字段赋值
        fieldInfo.SetValue(obj, 1);
        //获取所有属性的信息
        PropertyInfo[] propertyInfos = type.GetProperties();
        string[] strings = {"李四", "阿姆斯特朗回旋炮", "33cm"};
        //依次给属性属性赋值
        for (int i = 0; i < propertyInfos.Length; i++)
        {
            propertyInfos[i].SetValue(obj, strings[i], null);
        }

        //根据名字找到方法的信息
        MethodInfo methodInfo = type.GetMethod("StartMove");
        //执行方法
        methodInfo.Invoke(obj, null);
        //根据名字找到方法的信息
        MethodInfo methodInfo2 = type.GetMethod("ShowRanking");
        //执行方法
        methodInfo2.Invoke(obj, null);
    }
}

最后说个秘密,我有个C友叫李四。🙈🙈🙈

总结

欢迎大佬多多来给萌新指正,欢迎大家来共同探讨。
如果各位看官觉得文章有点点帮助,跪求各位给点个“一键三连”,谢啦~

声明:本博文章若非特殊注明皆为原创原文链接
https://blog.csdn.net/Wrinkle2017/article/details/119651165
————————————————————————————————

版权声明

版权声明:本博客为非营利性个人原创
所刊登的所有作品的著作权均为本人所拥有
本人保留所有法定权利,违者必究!
对于需要复制、转载、链接和传播博客文章或内容的
请及时和本博主进行联系
对于经本博主明确授权和许可使用文章及内容的
使用时请注明文章或内容出处并注明网址
转载请附上原文出处链接及本声明

  • 17
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值