[C#] 리플렉션 ( Reflection )

허은혜·2024년 1월 21일

CSharp

목록 보기
1/1

Reflection


런타임에 객체의 클래스 타입, 메서드, 프로퍼티 등의 메타 데이터를 알아내는 기능을 제공한다.
또한 동적으로 인스턴스를 만들 수도 있고, 그 인스턴스의 메서드를 호출할 수도 있다.

System.Type


모든 데이터 형식은 System.Object 형식을 상속받는다.
System.Object는 GetType() 메서드를 갖고 있는데, 이 메서드는 System.Type 형식을 반환한다.

이 Type 형식은 데이터 형식의 모든 정보를 담고 있다.
형식 이름, 소속된 어셈블리 이름, 필드 목록, 프로퍼티 목록, 메서드 목록 등을 포함한다.

int a = 0;
Type type = a.GetType();
FieldInfo[] fields = type.GetFields();

메타 데이터 읽어 오기


GetXXX() 형태의 메서드들을 이용하여 원하는 데이터를 얻을 수 있다.

메서드반환 형식설명
GetFieldsFieldInfo[]해당 형식의 필드 목록을 반환
GetMethodsMethodInfo[]해당 형식의 메서드 목록을 반환
GetPropertiesPropertyInfo[]해당 형식의 프로퍼티 목록을 반환
GetMembersMemberInfo[]해당 형식의 멤버 목록을 반환
GetGenericArgumentsType[]해당 형식의 형식 매개 변수 목록을 반환
...

GetXXX() 메서드의 인자

보다 정확한 정보를 얻기 위해 옵션을 추가할 수 있다.
열거형인 System.Reflection.BindingFlags을 조합하여 조회할 수 있다.
public, nonpublic

객체 생성


System.Activator.CreateInstance()

System.Activator 클래스에게 System.Type 객체를 입력하여 인스턴스를 생성할 수 있다.
이를 이용해서 프로그램이 조금 더 동적으로 동작할 수 있도록 구성할 수 있다.

Object a = Activator.CreateInstance(typeof(int));

Generic 타입으로부터 객체 생성

클래스 타입이 확정되지 않은 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);
profile
C# / Unity / 게임 개발

0개의 댓글