본문 바로가기

IT 살이/04. 기술 - 프로그래밍

개발 프레임워크 만들기 대장정 11- Contructor Injection

이전 포스트에서는 Unity 컨테이너는 자신에 등록된 타입들의 메소드(constructor, setter 속성, 일반 메소드)를 호출할때  "특별한 표시"가 있으면 dependency injection 메커니즘을 활성화 시킨다는 말을 했다. 그 특별한 표시는 어트리뷰트를 이용한다. 그 어트리뷰트는 메소드 타입 즉  constructor, setter 속성, 일반 메소드에 따라 다르다. 이제 이 포스트에서는 세개의 표시를 어떻게 하는지 그리고 그 표시들에 따라서 Unity 컨테이너는 어떻게 작동하는지 즉 dependency injection이 뭔지 좀 더 자세히 알아보자.

● Constructor Injection 표시

Constructor가 호출될때 DI 메커니즘을 활성시키는 방법에는 상황에 따라서 두가지가 있다.

▶ 정의된 Constructor가 하나밖에 없는 경우

이때는 아무 표시를 해 주지 않아도 자동으로 dependency 객체를 생성해서 injection시켜준다.  앞의 로거 예제에서 이미 본적이 있다.

public Biz01(ILogger logger)

{

    this.logger = logger;


    // 비즈니스 객체가 생성될때 로그를 남긴다.

    logger.Write("Biz01 생성자 호출" );

}

contructor의 파라미터로 ILogger 타입의 객체를 사용하고 있다. 이 타입의 인스턴스를 생성하는 코드는 다음과 같았다.

//Biz01 객체를 생성한다.

Biz01 biz1 = container.Resolve<Biz01>();

이 코드는 Biz01타입의 객체를 원한다는 것을 컨테이너에 알려주는 것이다. 그러나 코드상에서는 Biz01 constructor에서 사용하고 있는 ILogger 타입의 인스턴스를 건네주지는 않고 있다. 컨테이너는 ILogger 타입이 등록되었는지를 확인한다. ILogger 타입의 실제 타입으로 FSLogger가 등록되어 있다는 것을 확인하고 FSLogger 객체를 생성해서 Biz01 생성의 파라미터로 넘겨준다. 그렇게 생성된 Biz01 객체를 코드에 반환한다. 이것이 contructor  injection이다. 유가릿?

때로는 constructor도 여러개가 있을 수 있다. 이런 경우는 컨테이너에게 어떤 녀석을 호출할지를 알려줘야 한다.

InjectionContructorAttribute

public class MyObject

{


    public MyObject(SomeClassA objA, SomeClassB objB)

    {

        //...

    }


    [InjectionConstructor]

    public MyObject(DependentClassA depA, DependentClassB depB)

    {

        //...

    }

}

컨테이너에게 MyObject 객체를 요구하면 컨테이너는 [InjectionConstructor]가 표시된 constructor를 호출한다. 이 contructor에는 두 개의 종속된 타입 DependentClassA, DependentClassB가 존재한다. 컨테이너는 두 종속 타입의 인스턴스를 생성해서 대상 클래스의 생성에 inject 시킨다.

대상 클래스가 constructor를 여러개의 버전으로 정의하고 있는 경우, Unity는 InjectionConstructor 어트리뷰트가 표시되어 있는 버전을 호출한다. constructor가 여러개 있는데도 InjectionConstructor 어트리뷰트 표시가 없으면 Unity는 한번 더 고민을 하게된다. 그래서 contructor의 파라미터수가 가장 많은 것을 호출한다. 만약 가장 많은 수의 파라미터를가진 constructor가 여러개 존재하면 예외가 발생한다.