개인 공부/C#

유니티 리플렉션 (Reflection)

smallship 2024. 7. 19. 13:39

유니티에서 리플렉션은 프로그램 실행중에 자신의 구조를 가져오거나 수정할 수 있는 기능이다. 컴파일 타임에 객체를 조작하는것이 아닌 프로그램 실행중에 정보를 얻을 수 있으며 이를 사용하여 동적 로딩, 일반화, 메소드 호출 등 다양한 작업을 수행할 수 있다.

 

using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Unity.VisualScripting;
using UnityEngine;

public class ReflectionExample : MonoBehaviour
{
    private int exampleInt = 10;
    public int exampleInt2 = 20;
    // Start is called before the first frame update
    void Start()
    {
        System.Type myType = typeof(ReflectionExample);
        System.Type myType2=this.GetType();

        Debug.Log($"myType.Name : {myType.Name}");
        Debug.Log($"myType2.Name : {myType2.Name}");

        //public 멤버 함수를 가져와서 호출한다
        MethodInfo exampleFunctionMethodInfo =  myType.GetMethod("ExampleFunction");
        exampleFunctionMethodInfo?.Invoke(this, null);

        // non public(private or protected) 함수를 가져와서 호출한다.
        MethodInfo exampleFunction2MethodInfo = myType.GetMethod("ExampleFunction2", BindingFlags.NonPublic | BindingFlags.Instance);
        exampleFunction2MethodInfo?.Invoke(this, null);

         //non public 멤버 변수를 가져온다.
        FieldInfo exampleIntInfo = myType.GetField("exampleInt", BindingFlags.NonPublic | BindingFlags.Instance);
        exampleIntInfo?.SetValue(this, 50);

        Debug.Log($"example int value : {exampleIntInfo?.GetValue(this)}");
        Debug.Log($"example int value real member : {exampleInt}");

        // public 멤버 변수를 가져온다.
        FieldInfo exampleIntInfo2 = myType.GetField("exampleInt2");
        Debug.Log($"example in2t value : {exampleIntInfo?.GetValue(this)}");
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void ExampleFunction()
    {
        Debug.Log("Called ExampleFunction");
    }

    void ExampleFunction2()
    {
        Debug.Log("Called ExampleFunction2");
    }

    public void ExampleFunction3()
    {
        Debug.Log("Called ExampleFunction3");
    }
}

 

 

리플렉션을 사용하여 클래스의 메서드와 필드에 접근하고 값을 변경하고 호출하는 방법이다. typeof 연산자나 GetType() 메서드를 사용하여 객체의 Type을 얻는다. GetMethod() 메서드를 사용하여 메서드를 가져온 후 Invoke() 메서드로 호출한다. BindingFlags를 사용하여 private 메서드도 호출할 수 있다. GetField() 메서드를 사용하여 필드를 가져온 후 SetValue()와 GetValue()로 값을 변경하거나 조회한다.

 

 

 

 

둘다 리플렉션을 통해 설정된 50이 출력된다.

 

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


public class ReflectionClass
{
    public ReflectionClass()
    {
        Debug.Log("Created ReflectionClass");
    }

    public ReflectionClass(int a, int b)
    {
        Debug.Log($"Created ReflectionClass with member values : a : {a} b : {b} ");
    }
}
public class ReflectionExampleFriend : MonoBehaviour
{
    ReflectionExample _cachedExample;
    // Start is called before the first frame update
    void Start()
    {
        MethodInfo method = typeof(GameObject).GetMethod("GetComponent", new System.Type[] { typeof(System.Type) });

        _cachedExample = method?.Invoke(gameObject, new object[] { typeof(ReflectionExample) }) as ReflectionExample;
        _cachedExample.ExampleFunction3();

        ReflectionClass instance = Activator.CreateInstance(System.Type.GetType("ReflectionClass")) as ReflectionClass;
        ReflectionClass instance2 = Activator.CreateInstance(System.Type.GetType("ReflectionClass"), new object[] { 1, 2 }) as ReflectionClass;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

typeof(GameObject).GetMethod("GetComponent")를 사용하여 GameObject의 GetComponent 메서드를 가져와 Reflection을 통해 호출한다. 이를 통해 ReflectionExample 타입의 인스턴스를 얻는다.

 Activator.CreateInstance()를 사용하여 Reflection을 통해 클래스를 생성한다. 생성자의 매개변수를 전달하여 다양한 생성자를 호출할 수 있다.

 

 

ExampleFunction3 메서드 출력값과 매개변수 없는 인스턴스 생성자와 매개변수 전달하여 생성된 생성자가 호출된다.

 


리플렉션은 유연성과 동적 프로그래밍 기능을 제공하지만, 성능 저하와 코드의 가독성 및 유지보수성에 일정한 제약이 따른다. 따라서 사용 시 성능과 관리적인 측면을 고려하여 적절히 활용하는 것이 중요다. 주로 런타임에 동적인 작업이 필요한 경우나 메타프로그래밍 기법을 구현할 때 리플렉션을 활용할 수 있다.

'개인 공부 > C#' 카테고리의 다른 글

델리게이트(delegate)와 이벤트 (event)  (1) 2024.07.26
추상 클래스  (0) 2024.07.26
튜플  (0) 2024.07.25
LINQ (Language Integrated Query)  (0) 2024.07.12
파일 입출력  (0) 2024.07.12