.NET Reflection
.NET Reflection은 .NET 객체의 클래스 타입, 메서드, 프로퍼티 등의 메타 정보를 런타임 중에 알아내는 기능을 제공한다. 또한, 이러한 메타 정보를 얻은 후, 직접 메서드를 호출하거나 프로퍼티를 변경하는 등의 작업도 가능하다. 물론 객체에서 메서드를 직접 호출하는 경우가 더 빠르겠지만, 어떤 경우는 런타임중에 이런 메타 정보가 동적으로 알아낼 필요가 있다. 예를 들어, 테스트 어셈블리에 있는 테스트 클래스들의 Public 메서드를 선별해서 이를 동적으로 호출하는 경우라든가, 특정 클래스 안에 지정된 이름의 멤버가 있는지 판단하는 경우 등등에 .NET Reflection이 활용될 수 있다.
.NET Reflection을 이용한 프로퍼티 설정
.NET Reflection을 이용해서 많이 사용되는 케이스의 하나로 프로퍼티를 접근하는 경우를 들어 보자. 클래스의 프로퍼티 정보를 얻기 위해서 우선 .NET 클래스를 GetType() 등의 메서드를 써서 알아낸 후, 클래의 특정 속성정보를 알기 위해 Type.GetProperty()라는 메서드를 호출한다. 클래스가 가진 모든 프러퍼티를 가져오기 위해서는 GetProperties()라는 메서트를 호출하면 된다. 아래의 예제는 해당 객체가 Name이라는 속성을 가지고 있는지 체크해서, 만약 있으면, 특정 값을 그 속성에 설정하는 예이다.
예제
class Program
{
static void Main(string[] args)
{
MyClass1 m1 = new MyClass1();
SetDefaultName(m1);
Console.WriteLine(m1.Name);
}
static void SetDefaultName(object myObject)
{
// Name이라는 속성이 있는지?
PropertyInfo pi = myObject.GetType().GetProperty("Name");
// 있으면 속성값 설정
if (pi != null)
{
pi.SetValue(myObject, "Lee", null);
}
}
}
class MyClass1
{
public string Name { get; set; }
}
{
static void Main(string[] args)
{
MyClass1 m1 = new MyClass1();
SetDefaultName(m1);
Console.WriteLine(m1.Name);
}
static void SetDefaultName(object myObject)
{
// Name이라는 속성이 있는지?
PropertyInfo pi = myObject.GetType().GetProperty("Name");
// 있으면 속성값 설정
if (pi != null)
{
pi.SetValue(myObject, "Lee", null);
}
}
}
class MyClass1
{
public string Name { get; set; }
}
.NET Reflection을 이용한 메서드 호출
.NET Reflection을 이용해서 메서드 프로토타입 즉, 함수 인자, 리턴값 등의 메타 정보를 읽어 오는 것이 가능하며, 이를 통해 직접 그 메서드를 호출하는 것이 가능하다. 특정 메서드 정보를 얻기 위해서 Type.GetMethod()를 호출하고, 모든 메서드 정보를 가져오기 위해서는 GetMethods()를 호출한다. 아래의 예제는 해당 객체가 MyMethod이라는 메서드를 가지고 있는지 체크해서, 만약 있으면 해당 메서드를 호출하는 예이다.
예제
class Program
{
static void Main(string[] args)
{
MyClass1 m1 = new MyClass1();
MyClass2 m2 = new MyClass2();
MyClass3 m3 = new MyClass3();
MyFunc(m1);
MyFunc(m2);
MyFunc(m3);
}
static void MyFunc(object myObject)
{
// 해당 객체가 MyMethod라는 메서드를 가지고 있는지
MethodInfo mi = myObject.GetType().GetMethod("MyMethod");
if (mi != null)
{
// 만약 메서드가 있으면, 호출
mi.Invoke(myObject, null);
}
else
{
Console.WriteLine(myObject.GetType().Name +
": MyMethod not found");
}
}
}
// 아래는 테스트 클래스들
class MyClass1
{
public void MyMethod()
{
Console.WriteLine("MyClass1.MyMethod");
}
}
class MyClass2
{
public void MyMethod()
{
Console.WriteLine("MyClass2.MyMethod");
}
}
class MyClass3
{
public void DifferentMethod()
{
Console.WriteLine("MyClass3.DifferentMethod");
}
}
{
static void Main(string[] args)
{
MyClass1 m1 = new MyClass1();
MyClass2 m2 = new MyClass2();
MyClass3 m3 = new MyClass3();
MyFunc(m1);
MyFunc(m2);
MyFunc(m3);
}
static void MyFunc(object myObject)
{
// 해당 객체가 MyMethod라는 메서드를 가지고 있는지
MethodInfo mi = myObject.GetType().GetMethod("MyMethod");
if (mi != null)
{
// 만약 메서드가 있으면, 호출
mi.Invoke(myObject, null);
}
else
{
Console.WriteLine(myObject.GetType().Name +
": MyMethod not found");
}
}
}
// 아래는 테스트 클래스들
class MyClass1
{
public void MyMethod()
{
Console.WriteLine("MyClass1.MyMethod");
}
}
class MyClass2
{
public void MyMethod()
{
Console.WriteLine("MyClass2.MyMethod");
}
}
class MyClass3
{
public void DifferentMethod()
{
Console.WriteLine("MyClass3.DifferentMethod");
}
}