Reflection 이란?

 객체의 클래스 타입, 메서드, 프로퍼티 등의 메타 정보를 런타임 중에 알아내는 기능이다. 알아낸 정보를 통해 메서드를 호출하거나, 특정한 값을 불러오고 새로운 값을 할당할 수도 있다. 해당 정보를 직접 호출하여 원하는 동작을 수행할 수도 있지만 런타임 도중 동적으로 로드하거나 사용해야 하는 경우 주로 사용한다. 

 또한, 사용하려는 클래스나 메서드가 public이 아닌 경우, 다른 클래스에서 이를 사용할 수 없기 때문에 백도어처럼 사용하기도 한다.

 

Refelction 사용 방법

Assembly.GetType으로 접근하려는 Type 검색

 Reflection을 사용하기 위해서는 Assembly.GetType을 통해 접근하고자 하는 클래스의 Type을 찾아야 한다. Type이라는 용어가 다소 생소할 수도 있는데, 클래스명 = Type이라고 생각하면 된다.

 

적용 예시

public Type GetAuthDataManagerType()
	{
    	//모든 assembly를 검색합니다.
		foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
		{
			var test3 = assembly.GetTypes();
			foreach (var type in assembly.GetTypes())
			{
            	//찾는 Type이 있을 경우 반환합니다.
				if (type.FullName.Equals("Transportation.TestObject") == true)
				{
					return type;
				}
			}
		}
		return default;
	}

 

특정 Method를 호출하는 경우

 찾은 Type(클래스)에 존재하는 메소드를메서드를 호출하려는 경우, Type.GetMethod를 통해 호출할 수 있다. MethodInfo 형식을 리턴하며 해당 메서드를 실행하려면 Invoke를 통해 호출할 수 있는데, 이때 첫 번째 파라미터에는 어떤 클래스에 있는 메서드를 호출할 것인지에 대한 오브젝트 정보, 두 번째 파라미터에는 해당 메서드의 파라미터 값을 넣어야 한다.

 

적용 예시 1 - 일반적인 상황

public bool GetMethod(object myObject,Type type, string value)
	{
		var method = type.GetMethod("TestMethod");

		//찾지 못했다면 false를 리턴합니다.
		if (method == null)
		{
			return false;
		}

		// 메소드에 파라미터가 없을경우
		method?.Invoke(myObject, null);

		// 메소드에 파라미터가 필요할 경우
		method?.Invoke(myObject, new object[] { value });

		return true;
	}

 

적용 예시 2 - 사용하고자 하는 메서드가 singleton인 경우

public bool GetMethod(Type type, string value)
	{
		var method = type.GetMethod("TestMethod");

		//찾지 못했다면 false를 리턴합니다.
		if (method == null)
		{
			return false;
		}

		// Instance로 선언된 프로퍼티를 가져옵니다.
		var property = type.GetProperty("Instance");

		//찾지 못했다면 false를 리턴합니다.
		if (property == null)
		{
			return false;
		}

		//Getvalue를 통해 프로퍼티의 오브젝트 정보를 받아와 파라미터로 넘겨줍니다.
		method?.Invoke(property.GetValue(null), new object[] { value });
		return true;
	}

 

특정 Property에 접근하는 경우

 property에 접근하기 위해서는 Type.GetProperty를 통해 접근할 수 있다. 접근한 Property에서는 GetValue와 SetValue 메서드를 통해 프로퍼티 값을 설정할 수 있으며, 마찬가지로 접근하고자 하는 오브젝트를 파라미터로 받는다.

 

적용 예시

public bool GetProperty(object myObject,Type type, string value)
	{
		//TestProperty라는 이름을 가진 프로퍼티를 가져옵니다.
		var property = type.GetProperty("TestProperty");

		if (property == null)
		{
			return false;
		}

		//특정 object의 값을 받아옵니다.
		var object2 = property.GetValue(myObject);

		if (object2 == null)
		{
			return false;
		}

		//특정 object에 값을 할당합니다.
		property.SetValue(object2, value);

		return true;
	}

 

BindingFlags의 활용(확장)

 Reflection은 모든 메타 정보에 접근할 수 있는 만큼 검색해야 하는 정보도 많아질 수 있는데 이를 해결하기 위해 BindingFlags를 사용하여 필터링하여 검색할 수 있다. (FlagsAttribute 리스트)

 

적용 예시

public bool GetProperty(object myObject,Type type, string value)
	{
		//TestProperty라는 이름을 가진 프로퍼티를 가져옵니다. + public 멤버 및 Instance 멤버를 검색에 포함합니다.
		var property = type.GetProperty("TestProperty", BindingFlags.Public | BindingFlags.Instance);

		if (property == null)
		{
			return false;
		}

		//특정 object의 값을 받아옵니다.
		var object2 = property.GetValue(myObject);

		if (object2 == null)
		{
			return false;
		}

		//특정 object에 값을 할당합니다.
		property.SetValue(object2, value);

		return true;
	}

 

Reference

https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/concepts/reflection