» C#의 Reflection

C#의 Reflection

by DUBUKIMCH

C#의 Reflection은 프로그램이 런타임에 클래스, 메서드, 속성, 필드 등의 타입 정보를 탐색하고 조작할 수 있는 기능입니다. Reflection은 주로 애플리케이션에서 특정 객체의 타입을 모르거나, 객체의 속성이나 메서드를 동적으로 사용해야 할 때 유용합니다.

Reflection의 주요 기능

  1. 타입 정보 탐색: 클래스 타입을 알아내고, 속성, 메서드, 이벤트 등의 정보를 가져올 수 있습니다.
  2. 동적 인스턴스 생성: 클래스 타입만 알고 있는 상태에서 객체를 동적으로 생성할 수 있습니다.
  3. 메서드 호출: 메서드 이름만 알고 있을 때 메서드를 동적으로 호출할 수 있습니다.
  4. 속성 및 필드 접근: 객체의 속성이나 필드를 런타임에 동적으로 설정하거나 값을 가져올 수 있습니다.

Reflection을 사용하는 방법

Reflection을 사용하려면 주로 System.Reflection 네임스페이스에서 제공하는 Type 클래스를 사용합니다.

using System;
using System.Reflection;

예제 1: 타입 정보 조회하기

Reflection을 사용하여 특정 객체의 타입을 확인하고, 해당 타입의 메서드나 속성을 조회할 수 있습니다.

using System;
using System.Reflection;

public class MyClass {
    public string Name { get; set; }
    public int Age { get; set; }

    public void PrintInfo() {
        Console.WriteLine($"Name: {Name}, Age: {Age}");
    }
}

public class Program {
    public static void Main() {
        Type type = typeof(MyClass);

        // 클래스 이름 및 속성, 메서드 출력
        Console.WriteLine("Class: " + type.Name);
        
        Console.WriteLine("\nProperties:");
        foreach (PropertyInfo property in type.GetProperties()) {
            Console.WriteLine(property.Name);
        }
        
        Console.WriteLine("\nMethods:");
        foreach (MethodInfo method in type.GetMethods()) {
            Console.WriteLine(method.Name);
        }
    }
}

출력 예시:

Class: MyClass

Properties:
Name
Age

Methods:
PrintInfo
Equals
GetHashCode
GetType
ToString

예제 2: 동적 객체 생성 및 속성 값 설정

Reflection을 통해 특정 클래스의 인스턴스를 생성하고 속성 값을 설정할 수 있습니다.

using System;
using System.Reflection;

public class MyClass {
    public string Name { get; set; }
    public int Age { get; set; }

    public void PrintInfo() {
        Console.WriteLine($"Name: {Name}, Age: {Age}");
    }
}

public class Program {
    public static void Main() {
        Type type = typeof(MyClass);
        
        // 동적으로 객체 생성
        object instance = Activator.CreateInstance(type);
        
        // 속성 값 설정
        PropertyInfo nameProperty = type.GetProperty("Name");
        nameProperty?.SetValue(instance, "Alice");

        PropertyInfo ageProperty = type.GetProperty("Age");
        ageProperty?.SetValue(instance, 30);

        // 메서드 호출
        MethodInfo printMethod = type.GetMethod("PrintInfo");
        printMethod?.Invoke(instance, null); // 출력: Name: Alice, Age: 30
    }
}

출력 예시:

Name: Alice, Age: 30

예제 3: 메서드 호출

Reflection을 사용해 메서드 이름을 문자열로 전달하고, 그 메서드를 런타임에 호출할 수 있습니다.

using System;
using System.Reflection;

public class MathOperations {
    public int Add(int a, int b) => a + b;
}

public class Program {
    public static void Main() {
        Type type = typeof(MathOperations);
        
        // 객체 생성
        object instance = Activator.CreateInstance(type);

        // 메서드 호출
        MethodInfo addMethod = type.GetMethod("Add");
        var result = addMethod?.Invoke(instance, new object[] { 10, 20 });
        
        Console.WriteLine($"Result of Add: {result}");  // 출력: Result of Add: 30
    }
}

출력 예시:

Result of Add: 30

예제 4: 비공개 필드에 접근하기

Reflection을 사용해 일반적으로 접근할 수 없는 비공개 필드에 접근할 수 있습니다.

using System;
using System.Reflection;

public class Secret {
    private string secretMessage = "This is a secret";
}

public class Program {
    public static void Main() {
        Secret secretInstance = new Secret();
        Type type = typeof(Secret);

        // 비공개 필드 접근
        FieldInfo field = type.GetField("secretMessage", BindingFlags.NonPublic | BindingFlags.Instance);
        string message = (string)field?.GetValue(secretInstance);
        
        Console.WriteLine($"Secret Message: {message}"); // 출력: Secret Message: This is a secret
    }
}

출력 예시:

Secret Message: This is a secret

예제 5: 어셈블리에서 타입 및 메서드 검색

Reflection은 특정 어셈블리에서 클래스 및 메서드를 탐색하는 데 사용할 수도 있습니다.

using System;
using System.Reflection;

public class Program {
    public static void Main() {
        // 현재 어셈블리 가져오기
        Assembly assembly = Assembly.GetExecutingAssembly();
        
        Console.WriteLine("Types in Assembly:");
        foreach (Type type in assembly.GetTypes()) {
            Console.WriteLine(type.Name);
            
            Console.WriteLine("Methods:");
            foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
                Console.WriteLine(" - " + method.Name);
            }
        }
    }
}

이 예제는 현재 실행 중인 어셈블리에서 모든 타입을 검색하고, 각 타입 내의 메서드를 출력합니다.

Reflection의 주의 사항

  • 성능 저하: Reflection은 런타임에 타입 정보를 조사하고, 메서드 호출 등을 동적으로 수행하므로 일반적인 코드 실행보다 속도가 느립니다.
  • 안전성 문제: 비공개 필드나 메서드에 접근하는 경우 코드의 예측 불가능한 동작이나 유지보수 어려움을 초래할 수 있습니다.
  • 사용 제한: 보안이 중요한 환경에서는 Reflection을 제한할 수 있습니다.

Reflection은 유연한 동적 프로그래밍을 가능하게 하지만, 성능과 유지보수 측면에서 신중하게 사용해야 합니다.

You may also like

Leave a Comment

error: Content is protected !!