20-0503 원격으로 개체생성하기

최용국·2020년 5월 9일
0

관용구

목록 보기
7/9

20-0503 원격으로 개체생성하기

개체를 동적으로 생성하고 싶을 때가 있다. new() 키워드를 통해 명시적으로 생성할 수도 있지만 경우에 따라 Type이나 혹은 클래스의 이름만으로 생성하고 싶을 때를 얘기하는 것이다.

두 가지 클래스를 이용해 원격 개체를 생성할 수 있다.

Activator

Activator 클래스 (System)

FormatterServices

FormatterServices 클래스 (System.Runtime.Serialization)

가장 큰 차이점은 매개변수로 원격 개체를 생성할 수 있냐 없냐의 차이라고 생각한다. 장점과 단점이 있지만 단순히 프로그램 내에서 원격 개체를 생성하는 것이 목적이라면 FormatterServices를 사용하는 것을 추천하고 프로그램 외부에서나 혹은 다른 원격지에서 생성되는 것을 정하는 것이라면 Activator를 추천한다.

차이점을 코드로 보면

class Person

public class Person
{
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
    public Person() : this(string.Empty, 0)
    {

    }
    public string Name { get; private set; }
    public int Age { get; private set; }
    public override string ToString()
    {
        return $"Name: {this.Name ?? "name is null"} Age: {this.Age}";
    }
}

Activator

var activatorPerson = Activator.CreateInstance(typeof(Person), "최용국", 28) as Person;
Console.WriteLine(activatorPerson);

Activator는 개체의 생성자가 없다면 원격 개체를 생성할 수 없다. 혹은 매개변수 있는 생성자가 Private으로 감춰져 있다면 BindingFlags를 활용해야한다.

var activatorPerson = Activator.CreateInstance(typeof(Person), 
                BindingFlags.Instance | BindingFlags.NonPublic, null, 
                new object[] { "최용국", 28 }, null) as Person;
Console.WriteLine(activatorPerson);

매개변수가 없는 기본 생성자는

var activatorPerson = Activator.CreateInstance(typeof(Person), true) as Person
Console.WriteLine(activatorPerson);

를 이용하면 된다.

또, AssemblyName과 TypeName으로도 개체를 생성할 수 있다.

var activatorPerson4 = Activator.CreateInstance("RemoteInstance", "RemoteInstance.Person", 
                true, BindingFlags.Instance | BindingFlags.Public, 
                null, new object[] { "최용국", 28 }, 
                System.Globalization.CultureInfo.CurrentCulture, null);
var person = activatorPerson4.Unwrap() as Person;
Console.WriteLine(person);

AssemblyName으로 개체를 생성하는 경우에는 반환값이 ObjectHandle 형식이기 때문에 Unwrap() 함수로 개체를 꺼내와야 한다.

개체의 type과 assembly를 이용해 아래와 같이 유연한 코드를 작성할 수 있다.

var type = typeof(Person).Assembly.GetTypes().Single(a => a.Name == "Person");
var activatorPerson = Activator.CreateInstance(type, "최용국", 28);
Console.WriteLine(activatorPerson);

FormatterServices

var formatterPerson = FormatterServices.GetUninitializedObject(typeof(Person)) as Person;
Console.WriteLine(formatterPerson);

FormatterServices는 매개변수를 전달할 수 없는 강력한 원격 개체 생성을 지원한다. 생성하고 싶은 클래스가 명시적으로 기본 생성자, 매개변수 있는 생성자가 없어도 된다. 물론 abstract class는 안된다.

소스 위치
github: https://github.com/opzerg/YGStudy.git
solution: 관용구
project RemoteInstance

profile
코딩합시다.

0개의 댓글