[C#] Reflection (리플렉션)

ssungho·2023년 7월 25일
0

💡 CSharp Study

목록 보기
7/7
post-thumbnail

💡 Reflection

프로그램의 런타임중에 코드에 대한 정보를 조사하고 조작할 수 있는 기능

Reflection 을 사용하면 객체가 가지고 있는 모든 정보를 런타임에 동적으로 뜯어보고 분석할 수 있고, 정보를 얻어 직접 메서드를 호출하거나 프로퍼티를 변경할 수 있다.


📝 사용 예제

// Program.cs
class Program
{
    private class Monster
    {
        public int hp;
        protected int attack;
        private float speed;

        private void Attack() { }
    }

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

        Type type = monster.GetType();

		// fieldInfo[]로 반환된다.
        var fields = type.GetFields(System.Reflection.BindingFlags.Public
                                    | System.Reflection.BindingFlags.NonPublic
                                    | System.Reflection.BindingFlags.Static
                                    | System.Reflection.BindingFlags.Instance);
        
        foreach (var field in fields)
        {
            string access = "protected";
            if (field.IsPublic)
                access = "public";
            else if(field.IsPrivate)
                access = "IsPrivate";
            
            Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");
        }
    }
}

C#의 모든 객체들은 Object에서 파생되어 나오기 때문에 Object에 정의된 함수들을 사용할 수 있다

  • GetType(), Equals(), ToString(), GetHashCode() 등등

GetType()

  • GetType()을 이용하여 객체가 가지고 있는 모든 정보를 알 수 있고, 그 정보를 Type자료형에 담을 수 있다.

GetFields()

  • GetFields()를 이용하여 Type이 가지고 있는 멤버들 즉, 필드를 FieldInfo타입의 배열로 반환한다.
  • BindingFlags를 매개변수로 하여 검색 조건을 설정할 수 있다.
    • System.Reflection.BindingFlags.Public → public인 멤버 추출
  • BindingFlags의 종류 확인 -> 공식 문서

FieldInfo

  • 필드의 이름, 타입, 속성 등에 대한 정보를 얻을 수 있는 속성과 메서드를 가지고 있다.
    ```csharp
    foreach (var field in fields) // field는 FieldInfo를 의미함.
    {
        string access = "protected";
        if (field.IsPublic) // 필드가 public인지 판별
            access = "public";
        else if(field.IsPrivate) // 필드가 private인지 판별
            access = "IsPrivate";
        
    	// 접근 한정자, 필드의 자료형, 필드의 이름을 출력
        Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");
    }
    ```
  • access: foreach문 안의 조건문을 이용하여 접근 한정자를 기록한다.
  • field.FieldType.Name: 필드의 자료형을 반환한다.
  • field.Name: 필드의 이름을 반환한다.
    • 참고로 Singlefloat과 같다.
  • FieldInfo의 속성과 메서드 종류 확인 -> 공식 문서

Reflection을 이용하면 클래스의 x-ray를 찍는 것과 같다.


💡 Attribute

코드에 메타데이터를 추가하는 방법을 제공한다.

주석은 프로그래머들이 정보를 전달하기 위한 참고사항일 뿐 컴퓨터 입장에서 보면 컴파일 하지 않고 지나가지만 Attribute를 이용하면 런타임에서 참고할 수 있는 메타데이터(힌트)를 남길 수 있다.

📌 사용 방법

  1. Attribute로 이용할 클래스를 만들고 System.Attribute를 상속받는다.
  2. 멤버 변수나 메서드 바로 위에 [Attribute 이름]을 써준다.
  3. 생성자에 매개변수를 추가하여 추가 정보를 제공할 수 있다.

📝 사용 예제

// Program.cs
using System.Reflection;

class Program
{
    class Important : System.Attribute
    {
        private string messege;

        public Important(string messege) // 생성자를 이용하여 메세지를 입력한다.
        {
            this.messege = messege;
        }
    }
    
    private class Monster
    {
        [Important("Very Important")] // Attribute를 이용하여 중요한 멤버임을 나타낸다.
        public int hp;

        protected int attack;
        private float speed;

        private void Attack() { }
    }

    private 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 (var field in fields)
        {
            string access = "protected";
            if (field.IsPublic)
                access = "public";
            else if(field.IsPrivate)
                access = "IsPrivate";
            
            Console.WriteLine($"{access} {field.FieldType.Name} {field.Name}");

            var attributes = field.GetCustomAttributes();
        } 
    }
}

Custom Attribute 클래스 생성

class Important : System.Attribute
{
    private string messege;

    public Important(string messege) // 생성자를 이용하여 메세지를 입력한다.
    {
        this.messege = messege;
    }
}

Important라는 클래스를 만들고 System.Attribute를 상속받아 Custom Attribute를 만든다.

생성자에 messege라는 매개변수를 넣어 메세지를 남긴다.

Custom Attribute 사용

[Important("Very Important")]
public int hp;

hp라는 멤버에 Important를 추가해 Attribute를 붙여준다.

hpImportant라는 정보를 런타임에 알 수 있게 된 것이다.

추가적으로 hp"Very Important"라는 메세지를 담고 있는 것을 확인할 수 있다.

Attribute 확인

var attributes = field.GetCustomAttributes();

GetCustomAttributes() 를 이용하여 Attribute를 불러올 수 있다.


📝 정리

  • Reflection을 이용하여 런타임 중 객체의 모든 정보에 접근할 수 있다.
  • Attribute를 이용하여 런타임 중 참고할 수 있는 메타데이터를 남길 수 있다.

인프런 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문 강의를 듣고 공식 문서를 참고하여 정리한 글 입니다.

개인 공부를 정리한 글이기 때문에 틀린 부분이 있을 수 있습니다.

profile
클라이언트 개발자가 되는 그날까지 👊

1개의 댓글

진짜 지려요..

답글 달기

관련 채용 정보