런타임에 객체의 클래스 타입, 메서드, 프로퍼티 등의 메타 데이터를 알아내는 기능을 제공한다.
또한 동적으로 인스턴스를 만들 수도 있고, 그 인스턴스의 메서드를 호출할 수도 있다.
모든 데이터 형식은 System.Object 형식을 상속받는다.
System.Object는 GetType() 메서드를 갖고 있는데, 이 메서드는 System.Type 형식을 반환한다.
이 Type 형식은 데이터 형식의 모든 정보를 담고 있다.
형식 이름, 소속된 어셈블리 이름, 필드 목록, 프로퍼티 목록, 메서드 목록 등을 포함한다.
int a = 0;
Type type = a.GetType();
FieldInfo[] fields = type.GetFields();
GetXXX() 형태의 메서드들을 이용하여 원하는 데이터를 얻을 수 있다.
| 메서드 | 반환 형식 | 설명 |
|---|---|---|
| GetFields | FieldInfo[] | 해당 형식의 필드 목록을 반환 |
| GetMethods | MethodInfo[] | 해당 형식의 메서드 목록을 반환 |
| GetProperties | PropertyInfo[] | 해당 형식의 프로퍼티 목록을 반환 |
| GetMembers | MemberInfo[] | 해당 형식의 멤버 목록을 반환 |
| GetGenericArguments | Type[] | 해당 형식의 형식 매개 변수 목록을 반환 |
| ... |
보다 정확한 정보를 얻기 위해 옵션을 추가할 수 있다.
열거형인 System.Reflection.BindingFlags을 조합하여 조회할 수 있다.
public, nonpublic
System.Activator 클래스에게 System.Type 객체를 입력하여 인스턴스를 생성할 수 있다.
이를 이용해서 프로그램이 조금 더 동적으로 동작할 수 있도록 구성할 수 있다.
Object a = Activator.CreateInstance(typeof(int));
클래스 타입이 확정되지 않은 Generic Type의 경우 파라미터 T가 정해지지 않으면 객체를 생성할 수 없다. Generic Type 자체로는 클래스가 되지 못하기 때문이다.
먼저 GetGenericArguments()를 써서 T 파라미터 타입을 알아낸 후,
MakeGenericType(T)을 사용하여 정확한 클래스를 만들 수 있다.
public class GenericList<T>
{
private List<T> elements = new();
}
public class Program
{
public void Main
{
GenericList<int> nums = new GenericList<int>();
Run(nums);
}
public void Run(object obj)
{
// T 파라미터 타입 가져오기 - int
Type argType = obj.GetType().GetGenericArguments()[0];
// GenericList<>에 int를 적용하여 실제 타입 확정
Type actualType = typeof(GenericList<>).MakeGenericType(argType);
// 객체 생성
object obj = Activator.CreateInstance(actualType);
}
}
PropertyInfo 클래스의 경우, GetValue(), SetValue()라는 메서드가 존재한다.
GetValue() : 프로퍼티로부터 값을 읽기
SetValue() : 프로퍼티에 값을 할당
public class Profile
{
public string Name { get; set; }
}
public class Program
{
public void Run()
{
Type type = typeof(Profile);
Object profile = Activator.CreateInstance(type);
PropertyInfo name = type.GetProperty("Name");
name.SetValue(profile, "홍길동");
string currentName = name.GetValue(profile);
}
}
Name 이라는 이름의 프로퍼티에 값을 할당하고 읽어올 수 있다.
MethodInfo를 이용해 메서드를 호출할 경우, Invoke() 메서드를 사용할 수 있다.
public object Invoke (object obj, object[] parameters);
obj
메서드를 호출할 개체. 메서드가 static이면 이 인자는 무시된다.
parameters
호출된 메서드에 대한 인자 목록.
호출된 메서드의 매개 변수와 개수, 순서, 형식이 동일한 개체의 배열.
매개 변수가 없는 경우 null이어야 한다.
Object a = Activator.CreateInstance(type);
PropertyInfo name = type.GetProperty("Name");
name.SetValue(a, "홍길동");
MethodInfo method = type.GetMethod("Print");
method.Invoke(profile);