💡 프로그램의 런타임 중에 코드에 대한 정보를 조사하고 조작할 수 있는 기능
Reflection을 사용하면 객체가 가지고 있는 모든 정보를 런타임에 동적으로 뜯어보고 분석할 수 있고, 정보를 얻어 직접 매서드를 호출하거나 프로퍼티를 변경할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Temp
{
public int tempValue;
public int TempValue
{
get { return tempValue; }
set
{
tempValue = value;
}
}
public void Func()
{
Debug.Log("어떠한 기능");
}
}
public class ReflectionTest : MonoBehaviour
{
private void Start()
{
Temp temp = new Temp();
Debug.Log("타입이름 : " + temp);
}
}
using System.Reflection // 필수적으로 추가
public class ReflectionTest : MonoBehaviour
{
private void Start()
{
Temp temp = new Temp();
Debug.Log("타입이름 : " + temp.GetType().Name);
}
// GetType을 하여 클래스의 이름을 출력한 상태
// 클래스의 정보만을 가져온다
}
GetFields() : 맴버 변수들을 가져옴
GetPropertys() : 맴버 프로퍼티를 가져옴
GetMethods() : 맴버 함수들을 가져옴
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection; // 필수!
public class Player
{
public float currentHP;
public string name;
public void Test()
{
Debug.Log("Player의 매서드");
}
}
public class ReflectionTest : MonoBehaviour
{
private void Start()
{
Player player = new Player();
Type type; // 데이터 타입의 정보가 담겨있는 Type변수
type = player.GetType();
// player가 가지고 있는 데이터타입의 정보를 넘겨준다.
// player의 변수와 매서드는 아직 모르는 상태.
// player의 값이 아닌, 데이터 타입의 정보를 가져온 것.
// type.Test(); 사용불가
// type에는 클래스 자체만을 넘겨주었기 때문에 Test()함수를 이용할 수 없다
MethodInfo[] methos = type.GetMethods();
// type에 들어있는 Player의 맴버함수들을 보관하는 배열 methodInfo
foreach (MethodInfo method in methos)
{
Debug.Log("함수의 이름 : " + method.Name);
// Player 클래스 안의 모든 함수들을 확인해본다.
}
FieldInfo[] fields = type.GetFields();
// type에 들어있는 Player의 맴버변수들을 보관하는 배열 fields
foreach (FieldInfo field in fields)
{
Debug.Log("멤버 변수의 이름 : " + field.Name);
// Player 클래스 안의 모든 변수들을 확인해본다.
}
PropertyInfo[] properties = type.GetProperties();
// type에 들어있는 Player의 프로퍼티들을 보관하는 배열 properties
foreach (PropertyInfo property in properties)
{
Debug.Log("프로퍼티 이름 : " + property.Name);
// Player 클래스 안의 모든 프로퍼티들을 확인해본다.
}
}
}
////////////// 출력
// Player의 매서드
// 함수의 이름 : Test
// 함수의 이름 : Equals (파생) // c#의 모든 객체들은 Object에서 파생되어 나오기 때문에, Object에 정의된 함수 사용 가능
// 함수의 이름 : GetHashCode (파생)
// 함수의 이름 : GetType (파생)
// 함수의 이름 : ToString (파생)
// 맴버 변수의 이름 : currentHP
// 맴버 변수의 이름 : name
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection; // 필수!
public class Player
{
public float currentHP;
public float currentMana;
public string name;
}
public class ReflectionTest : MonoBehaviour
{
private void Start()
{
Player player = new Player();
Player player2 = new Player();
player.currentHP = 100;
player2.currentHP = 300; // 생성자를 통한 변수 설정
Type type;
type = player.GetType(); // Player클래스의 정보를 type에 전달
type.GetField("currentHP").SetValue(player, 400);
type.GetField("name").SetValue(player, "First Player");
type.GetField("currentMana").SetValue(player, 30.5f);
// SetValue의 매개변수 타입은 오브젝트이기 때문에 박싱을 통해들어가 어떤 데이터타입도 SetValue로 들어갈 수 있다
// 이 과정에서 내부에서 리플렉션이 일어나고 있는것!! 왜냐하면 박싱과 언박싱을하기 위해서는 클래스에 대한 메타 정보를 알고 있어야 하기 때문.
Debug.Log(type.GetField("currentHP").GetValue(player));
Debug.Log(type.GetField("currentHP").GetValue(player2));
Debug.Log(type.GetField("currentMana").GetValue(player));
// GetValue() 함수의 인자로 player를 안적어주면 GetValue 상태에서 어떤 녀석의 hp를 가져와줄지 모른다
// 왜냐하면 GetField 만으로는 Class에대한 메타 정보만을 가져와 주기 떄문
}
}
////////////// 출력
// 400
// 300
// 30.5
이때 주의할 것은, GetField만으로는 클래스의 객체(player, player2)에 대한 정보를 가져오는 것이 아닌, 데이터 타입의 정보만을 가져오게 된다. 그렇기 때문에, type = player.GetType(); 에서의 type만으로는 Player클래스에 만들어놓은 변수들을 불러오지 못한다. 그렇기 때문에, GetValue(player)이런 식으로 어떤 객체의 currentHP를 가져올 것인지 표현해 주어야 한다.