38
C#의 Reflection은 프로그램이 런타임에 클래스, 메서드, 속성, 필드 등의 타입 정보를 탐색하고 조작할 수 있는 기능입니다. Reflection은 주로 애플리케이션에서 특정 객체의 타입을 모르거나, 객체의 속성이나 메서드를 동적으로 사용해야 할 때 유용합니다.
Reflection의 주요 기능
- 타입 정보 탐색: 클래스 타입을 알아내고, 속성, 메서드, 이벤트 등의 정보를 가져올 수 있습니다.
- 동적 인스턴스 생성: 클래스 타입만 알고 있는 상태에서 객체를 동적으로 생성할 수 있습니다.
- 메서드 호출: 메서드 이름만 알고 있을 때 메서드를 동적으로 호출할 수 있습니다.
- 속성 및 필드 접근: 객체의 속성이나 필드를 런타임에 동적으로 설정하거나 값을 가져올 수 있습니다.
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은 유연한 동적 프로그래밍을 가능하게 하지만, 성능과 유지보수 측면에서 신중하게 사용해야 합니다.