Unity C# 游戏开发 反射 Reflection 案例讲解(图文详细,带源码)
Posted 水光涵月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity C# 游戏开发 反射 Reflection 案例讲解(图文详细,带源码)相关的知识,希望对你有一定的参考价值。
今天打球的小姐姐格外。。。
小姐姐为了感谢我最近的付出,邀请我一块打球,那我必须得把把赢她(钢铁直男的气势不能丢),不能给程序员丢脸,我被眼前的球晃的好晕🙈,很快小姐姐也没力气了,坐在了地上,说最近被反射搞得好迷糊🙈。
那我肯定不能惯着她😎,反射下,看小姐姐的脚本里都写了啥!!😎😎😎💛😻😻
Unity C# 游戏开发 反射 Reflection 案例讲解(图文详细,带源码)
一、反射是什么?
我们先来个官方的解释:这是官方的文档文档链接
反射提供了描述程序集、模块和类型的对象(类型为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 = {以上是关于Unity C# 游戏开发 反射 Reflection 案例讲解(图文详细,带源码)的主要内容,如果未能解决你的问题,请参考以下文章