.NET Reflection을 이용한 클래스 객체 생성
클래스 타입을 알 때 .NET Reflection을 이용해서 해당 클래스의 객체를 생성할 수 있다. 이는 컴파일시에 직접 new를 사용하는 방식이 아니라, 클래스 타입명을 문자열로 받아들여 런타임시에 해당 클래스의 객체를 생성할 수 있는 것을 뜻한다. 또한, 어떤 객체를 받아들여 해당 타입을 얻은 후에 (ex: obj.GetType()), 이 타입의 또 다른 객체를 생성하는 것도 가능하다. 아래의 예제는 해당 Customer라는 클래스명을 사용하여 런타임시에 해당 객체를 생성하는 예이다. Type.GetType()을 이용하여 해당 타입을 알아내고 (주: 클래스명 앞에 네임스페이스를 붙여야 한다), 이어 Activator의 CreateInstance()를 사용하여 실제 클래스 객체를 생성한다.
예제
namespace MyNamespace
{
using System;
using System.Diagnostics;
public class Class1
{
public void Run()
{
// 네임스페이스와 클래스명 함께
Type customerType = Type.GetType("MyNamespace.Customer");
// Type으로부터 클래스 객체 생성
object obj = Activator.CreateInstance(customerType);
// 생성된 객체 사용예
string name = ((Customer)obj).Name;
Debug.WriteLine(name); // No name
}
}
public class Customer
{
public Customer()
{
this.Name = "No name";
}
public int Id { get; set; }
public string Name { get; set; }
}
}
{
using System;
using System.Diagnostics;
public class Class1
{
public void Run()
{
// 네임스페이스와 클래스명 함께
Type customerType = Type.GetType("MyNamespace.Customer");
// Type으로부터 클래스 객체 생성
object obj = Activator.CreateInstance(customerType);
// 생성된 객체 사용예
string name = ((Customer)obj).Name;
Debug.WriteLine(name); // No name
}
}
public class Customer
{
public Customer()
{
this.Name = "No name";
}
public int Id { get; set; }
public string Name { get; set; }
}
}
Generic 타입으로부터 객체 생성
클래스 타입이 확정되지 않은 Generic Type인 경우에는 (ex: MyFilter<T>) 파라미터 T가 정해지지 않으면 Activator로 객체를 생성할 수 없다. 그것은 Generic Type 자체로는 클래스가 되지 못하기 때문인데, 이 경우 먼저 Generic의 T 파라미터 타입을 GetGenericArguments()를 써서 알아낸 후, MakeGenericType(T)을 사용하여 구체적인 클래스를 만들어야 한다. 아래 예제는 MyFilter라는 Generic 타입이 object로 Run()함수에 전달되었을 때, T 파라미터를 알아내고 Generic으로부터 객체를 생성하는 예를 보여주고 있다.
예제
using System;
using System.Collections.Generic;
using System.Diagnostics;
public class Class2
{
public Class2()
{
MyFilter<int> filter = new MyFilter<int>();
Run(filter);
}
public void Run(object filter)
{
// Type명 비교
if (filter.GetType().Name == typeof(MyFilter<>).Name)
{
// Generic의 T 파라미터 타입 가져오기 : int
Type genArgType = filter.GetType().GetGenericArguments()[0];
// MyFilter<>에 int를 적용하여 실제 타입 확정
Type actualType = typeof(MyFilter<>).MakeGenericType(genArgType);
// 실제 타입으로부터 객체 생성
object obj = Activator.CreateInstance(actualType, true);
Debug.WriteLine(obj.GetType().Name); //MyFilter`1
}
}
}
public class MyFilter<T> where T : struct
{
private List<T> _elements;
public MyFilter()
{
_elements = new List<T>();
}
public MyFilter(List<T> elements)
{
_elements = elements;
}
}
using System.Collections.Generic;
using System.Diagnostics;
public class Class2
{
public Class2()
{
MyFilter<int> filter = new MyFilter<int>();
Run(filter);
}
public void Run(object filter)
{
// Type명 비교
if (filter.GetType().Name == typeof(MyFilter<>).Name)
{
// Generic의 T 파라미터 타입 가져오기 : int
Type genArgType = filter.GetType().GetGenericArguments()[0];
// MyFilter<>에 int를 적용하여 실제 타입 확정
Type actualType = typeof(MyFilter<>).MakeGenericType(genArgType);
// 실제 타입으로부터 객체 생성
object obj = Activator.CreateInstance(actualType, true);
Debug.WriteLine(obj.GetType().Name); //MyFilter`1
}
}
}
public class MyFilter<T> where T : struct
{
private List<T> _elements;
public MyFilter()
{
_elements = new List<T>();
}
public MyFilter(List<T> elements)
{
_elements = elements;
}
}