정신과 시간의 방
카테고리
작성일
2022. 8. 23. 01:33
작성자
risehyun

C#과 유니티로 만드는 MMORPG 게임 개발 시리즈 강의를 수강하며 리플렉션 파트에서 배우고 느낀 점을 정리해보았다.

 


  • 리플렉션이란
    - 클래스가 가지고 있는 모든 정보들을 Runtime중에 뜯어보고 분석해볼 수 있는, 일종의 X-Ray라고 할 수 있다.

  • 사용 예제
using System.Reflection;

namespace CSharpStudy
{
    class Program
    {
        class Monster
        {
            public int hp;
            protected int attack;
            private float speed;

            void Attack() { }
        }

        static void Main(string[] args)
        {
            Monster monster = new Monster();

            Type type = monster.GetType(); 
            // C#의 모든 객체들은 Object에서 파생되기 때문에 GetType이란걸 들고있다.
            // 이걸 이용하면 객체의 타입을 빼낼 수 있다.
            // 이 type을 사용하면 클래스의 이름부터 내부 변수, 함수까지 
            // 모든 정보를 알 수 있다.

            var fields = type.GetFields(System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Static
                | System.Reflection.BindingFlags.Instance); // 지정한 정보들을 내뱉게 됨

            foreach (FieldInfo field in fields)
            { // 필드에 있는 정보를 추출해서 정보를 얻을 수 있다.
                string access = "protected";
                if (field.IsPublic)
                    access = "public";
                else if (field.IsPrivate)
                    access = "private";
                Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");
            }

        }

    }

}

실행결과. 참고로 여기서 나오는 Single은 float와 같은 의미이다.

이 밖에도 프로퍼티나 필드, 생성자 정보를 얻는 등 클래스 내부의 다양한 정보에 대해서 알 수 있다.

 

  • 애트리뷰트란?
    - 클래스나 메소드의 메타데이터를 기록할 수 있는 기능. 프로그래머끼리 정보를 전달할 수 있지만 컴퓨터는 사용할 수 없는 일반 주석과 달리 컴퓨터가 runtime중에도 체크하고 참고할 수 있는 힌트를 남길 수 있다.

  • 애트리뷰트 사용 예제
    class Program
    {
        class Important : System.Attribute
        {
            string massage;

            public Important(string massage) { this.massage = massage; }
        
        }

        class Monster
        {

            // hp입니다. 중요한 정보입니다. -> 이렇게 기록해도 컴퓨터는 인식하지 않음
            [Important("Very Important")] // 애트리뷰트에서 파생된 클래스를 선언함으로서 컴퓨터가 체크하게 됨
            public int hp;
            protected int attack;
            private float speed;

            void Attack() { }
        }

        static void Main(string[] args)
        {
            Monster monster = new Monster();

            Type type = monster.GetType();

            var fields = type.GetFields(System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Static
                | System.Reflection.BindingFlags.Instance); 

            foreach (FieldInfo field in fields)
            { 
                string access = "protected";
                if (field.IsPublic)
                    access = "public";
                else if (field.IsPrivate)
                    access = "private";

                var attributes = field.GetCustomAttributes();

                Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");
            }

        }

    }

애트리뷰트가 적용된 hp 변수에 대해서 massage가 나타남을 알 수 있다.

- 리플렉션과 애트리뷰트는  툴을 만들 때 특히 유용하다.

- 예를 들어서 유니티에서 public 상태로 변수를 입력하면 바로 인스펙터창에 해당 변수가 나타나는데, 이를 리플렉션 기능 없이 구현하려면 상당히 어려워질 것이다.

언리얼의 경우 C++에 리플렉션 기능이 없기 때문에 파일을 읽어와서 필드로 추정되는 값을 어딘가에 기억하도록 다른 파일을 이용해 간접적으로 관리하도록 만들게 되는데,

C#은 자체적으로 리플렉션을 지원하므로 필드의 값을 바로 체크하여 툴의 UI를 열어주게끔 구현할 수 있다.

 

엑셀을 참고해 무언가를 동적으로 구현할 때도 유용하게 쓸 수 있다.

 

- 유니티에서 private 변수의 값을 인스펙터에 나타내주는 SerializeField 키워드도 애트리뷰트인 일종인 주석 문법이다.

'C#' 카테고리의 다른 글

220823 Nullable (널러블)  (0) 2022.08.23
220822 Exception (예외 처리)  (0) 2022.08.22
220822 Event (이벤트)  (0) 2022.08.22
[C#] Delegate (대리자)  (0) 2022.08.21
220820 Property (프로퍼티) + 식 본문 멤버 (Expression-bodied members)  (0) 2022.08.20