C# - 리플렉션: 초보자 가이드
안녕하세요, 미래의 코딩 슈퍼스타! 오늘 우리는 C# 리플렉션의 세계로 흥미로운 여정을 떠납니다. 당신이 코드를 한 줄도 적지 않았다면 걱정하지 마세요 - 나는 당신의 친절한 안내자가 되어 이 주제를 함께 단계별로 탐구하겠습니다. 이 튜토리얼의 끝을 맺을 때, 당신은 리플렉션의 무엇인지와 어떻게 사용하는지에 대한 견고한 이해를 가지게 될 것입니다. 그럼 시작해 보겠습니다!
리플렉션은 무엇인가요?
상상해 보세요, 고급 레스토랑에서 당신은 메뉴를 받습니다. 하지만 이 메뉴는 마법의 메뉴입니다! 그저 요리를 볼 수 있는 것이 아니라, 부엌으로 가서 어떻게 만들어지는지, 사용된 재료는 무엇인지, 심지어 요리법을 실시간으로 수정할 수도 있습니다. 이것이 바로 C#에서 리플렉션하는 것입니다. 하지만 음식 대신 코드를 다루는 것입니다.
기술적으로 리플렉션은 C#의 기능으로, 프로그램이 실행 중에 자신의 구조와 행동을 검사하고 상호작용하며 수정할 수 있게 합니다. 프로그램이 자신을 돌아보는 거울을 주는 것과 같습니다!
리플렉션의 응용 사례
이제 여러분은 "왜 프로그램이 자신을 돌아보고 싶을까요?"라는 의문이 들 수 있습니다. 훌륭한 질문입니다! 리플렉션의 몇 가지 실질적인 응용 사례를 탐구해 보겠습니다:
-
동적로드 아セン블리: 리플렉션을 사용하면, 프로그램을 작성할 때 알지 못했던 아セン블리(코드 패키지)를 로드하고 사용할 수 있습니다.
-
타입의 인스턴스 생성: 컴파일 시간에 알지 못했던 특정 타입의 객체를 생성할 수 있습니다.
-
메서드 호출: 리플렉션을 사용하여 객체의 메서드를 동적으로 호출할 수 있습니다.
-
필드와 속성 접근 및 수정: 객체의 필드와 속성에 읽고 쓸 수 있습니다.
-
어트리뷰트 검사: 프로그램 요소에 첨부된 어트리뷰트(추가 정보)를 검사할 수 있습니다.
이제 이러한 내용을 코드 예제와 함께 더 자세히 살펴보겠습니다!
예제 1: 동적으로 인스턴스 생성
using System;
using System.Reflection;
class Program
{
static void Main()
{
// string 클래스의 타입을 가져옵니다
Type stringType = typeof(string);
// 리플렉션을 사용하여 string의 인스턴스를 생성합니다
object str = Activator.CreateInstance(stringType, new object[] { "Hello, Reflection!" });
Console.WriteLine(str); // 출력: Hello, Reflection!
}
}
이 예제에서 우리는 리플렉션을 사용하여 string
클래스의 인스턴스를 생성하고 있습니다. C#에게 "나는 무엇을 만들고 싶은지 알려주겠다"고 말하는 것과 같습니다. 이는 프로그램이 실행 중에 필요한 정확한 타입을 알지 못할 때 특히 유용합니다.
예제 2: 동적으로 메서드 호출
using System;
using System.Reflection;
class MyClass
{
public void SayHello(string name)
{
Console.WriteLine($"Hello, {name}!");
}
}
class Program
{
static void Main()
{
// MyClass의 인스턴스를 생성합니다
MyClass obj = new MyClass();
// MyClass의 타입을 가져옵니다
Type type = obj.GetType();
// SayHello 메서드의 MethodInfo를 가져옵니다
MethodInfo methodInfo = type.GetMethod("SayHello");
// 메서드를 호출합니다
methodInfo.Invoke(obj, new object[] { "Reflection" });
// 출력: Hello, Reflection!
}
}
여기서 우리는 리플렉션을 사용하여 MyClass
객체의 SayHello
메서드를 호출하고 있습니다. 이는 특정 타입의 메서드를 호출해야 하지만 컴파일 시간에 정확한 타입을 알지 못할 때 매우 유용합니다.
메타데이터 보기
리플렉션의 가장 멋진 기능 중 하나는 코드의 하드웨어를 들여다볼 수 있다는 것입니다. 우리는 타입, 메서드, 속성 등에 대한 메타데이터를 보고 있습니다. 이제 그것을 살펴보겠습니다!
예제 3: 타입 메타데이터 보기
using System;
using System.Reflection;
class Program
{
static void Main()
{
Type stringType = typeof(string);
Console.WriteLine($"Type Name: {stringType.Name}");
Console.WriteLine($"Full Name: {stringType.FullName}");
Console.WriteLine($"Namespace: {stringType.Namespace}");
Console.WriteLine($"Is it a class? {stringType.IsClass}");
Console.WriteLine($"Base Type: {stringType.BaseType}");
Console.WriteLine("\nMethods:");
foreach (MethodInfo method in stringType.GetMethods())
{
Console.WriteLine(method.Name);
}
}
}
이 코드는 string
클래스에게 자신에 대해 알려달라는 것과 같습니다. 우리는 그의 이름, 네임스페이스, 클래스 여부, 상속된 타입, 그리고 모든 메서드 목록을 확인하고 있습니다. 코드와의 대화와 같습니다!
종합 예제
이제 여러 가지 리플렉션 기능을 보여주는 더 복잡한 예제를 만들어 보겠습니다:
using System;
using System.Reflection;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void Introduce()
{
Console.WriteLine($"Hi, I'm {Name} and I'm {Age} years old.");
}
}
class Program
{
static void Main()
{
// 리플렉션을 사용하여 Person 객체를 생성합니다
Type personType = typeof(Person);
object[] constructorArgs = { "Alice", 30 };
Person person = (Person)Activator.CreateInstance(personType, constructorArgs);
// 리플렉션을 사용하여 속성 값을 가져오고 설정합니다
PropertyInfo nameProperty = personType.GetProperty("Name");
PropertyInfo ageProperty = personType.GetProperty("Age");
Console.WriteLine($"Current Name: {nameProperty.GetValue(person)}");
nameProperty.SetValue(person, "Bob");
ageProperty.SetValue(person, 25);
// 리플렉션을 사용하여 메서드를 호출합니다
MethodInfo introduceMethod = personType.GetMethod("Introduce");
introduceMethod.Invoke(person, null);
// Person 클래스의 모든 메서드를 표시합니다
Console.WriteLine("\nMethods of Person class:");
foreach (MethodInfo method in personType.GetMethods())
{
Console.WriteLine(method.Name);
}
}
}
이 예제는 리플렉션을 사용하여 객체를 생성하고, 속성 값을 가져오고 설정하고, 메서드를 호출하고, 클래스의 모든 메서드를 나열하는 것을 보여줍니다. 마치 우리가 Person
객체를 완전히 리플렉션을 통해 제어하는 것처럼 보입니다!
리플렉션 메서드 표
다음은 일부 흔한 리플렉션 메서드입니다:
메서드 | 설명 |
---|---|
Type.GetType() |
지정된 이름의 Type을 가져옵니다 |
Object.GetType() |
현재 인스턴스의 Type을 가져옵니다 |
Type.GetMethods() |
현재 Type의 모든 공개 메서드를 반환합니다 |
Type.GetProperties() |
현재 Type의 모든 공개 속성을 반환합니다 |
Type.GetFields() |
현재 Type의 모든 공개 필드를 반환합니다 |
Type.GetConstructors() |
현재 Type의 모든 공개 생성자를 반환합니다 |
Activator.CreateInstance() |
타입의 인스턴스를 생성합니다 |
MethodInfo.Invoke() |
메서드를 호출합니다 |
PropertyInfo.GetValue() |
속성의 값을 가져옵니다 |
PropertyInfo.SetValue() |
속성의 값을 설정합니다 |
결론
와우! 오늘 우리는 많은 내용을 다루었습니다. 리플렉션은처음에는 약간 마음을 쓰이지만, C# 도구 상자에서 매우 강력한 도구입니다. 리플렉션을 사용하면 프로그램이 더 유연하고 동적으로 변할 수 있어 실행 중의 조건에 적응할 수 있습니다.
하지만 강력한 권한은 큰 책임을 동반합니다. 리플렉션은 직접 코드보다 느릴 수 있으며, 신중하게 사용하지 않으면 타입 안전성을 깨뜨릴 수 있습니다. 하지만 신중하게 사용하면 다른 방법으로는 풀 수 없는 문제를 해결할 수 있습니다.
계속 연습하고 탐구하면, 얼마 지나지 않아 리플렉션을 마스터하고, 미래의 C# 마에스트로로 성장할 것입니다! 행복하게 코딩하세요!
Credits: Image by storyset