2016-09-28 4 views
0

IOC/DI 컨테이너를 사용하려고하지만 하위 창을 만들 때 가장 좋은 방법은 무엇입니까?IOC/DI 컨테이너 및 하위 창 만들기 딜레마

나는 데 딜레마는 다음과 같습니다

public class ParentWindow : Form 
{ 
    public void OpenChildWindow() 
    { 
     var child = IocContainer.Instance.Resolve<ChildWindow>(); // big issue !!! an-ti server locator pattern 
     child.Show(); 
    } 
} 

또는

public class ParentWindow : Form 
    { 

      private Container _container 

      public ParentWindow(Container container) // no, no, you have dependence on container 
      { 
      } 

     public void OpenChildWindow() 
     { 
      var child = _container.Resolve<ChildWindow>(); 
      child.Show(); 
     } 
    } 

내 솔루션

public class ParentWindow : Form 
{ 
    private IFormFactory _factory 

    public ParentWindow(IFormFactory factory) // inject from IOC container 
    { 
    } 

    public void OpenChildWindow() 
    { 
     var child = _factory.CreateChildWindow(); 
     child.Show(); 
    } 
} 

하지만 내 솔루션 , 가지 내 자신의 IOC 컨테이너가 될 내 공장, 내 모든 부모 - 자식 창이 공장을 통과해야합니다, 내 공장이 새로운 "서버 위치 지정자"가되지 않습니다.

더 좋은 해결책이 있습니까?

+0

관련 : https://stackoverflow.com/questions/38417654/winforms-how-to-register-forms-with-ioc-container/38421425#38421425 – Steven

+0

@Steven 디는 아무튼 사용하여 내 문제 – LeY

답변

0

DI를 사용한다는 것은 컨테이너를 서비스 로케이터로 사용한다는 것을 의미합니다. 정확히 한 번 실행되는 코드 한 줄로 사용하는 것이 좋습니다. 이를 컨테이너 루트가 구성되고 컨테이너가 구성되고 오브젝트 그래프의 루트가 작성됩니다.

예제의 최상위 코드가이 원칙을 위반하지 않습니다.

(!) 참고 :

나는 항상 내가 DI는 그것을 고려 easily- 더 많은 프레임 워크 전환 할 수 있도록 내 자신의 클래스와 컨테이너 프레임 워크 코드를 래핑 무엇

.

+0

가 해결되지 않습니다 컨테이너를 직접 소비하는 것을 의미하지는 않습니다. 심지어 스택 전체에 명시 적으로 종속성을 갖는 코드 냄새로 간주 될 수도 있습니다. 오히려, Composition Root와 Local Factory의 조합을 사용하면 컨테이너의 스택 의존성 상위 만 가질 수 있으며 모든 컨테이너에 전혀 의존하지 않고 모든 곳의 로컬 팩토리를 사용할 수 있습니다. –

+0

나는 완전히 동의한다. 그리고 이것은 내가 말했던 바로 그 것이다. - 당신이주의 깊게 읽으면 - 언급하지 않은 지역의 공장 부분을 빼십시오. (대답을 편집하여 명확하게 나타낼 수 있습니다). @WiktorZychla –

+0

CR은 단지 이야기의 절반에 불과하다는 점에 유의하십시오. 컨테이너를 구성 할 수 있지만 컨테이너를 스택 아래로 전달해야합니다. 지역 공장의 아이디어는 나머지 절반입니다. 현지 공장을 사용하면 컨테이너를 참조 할 필요가 없습니다. –

1

당신이 제안하는 해결책은 올바른 방향으로의 거대한 단계입니다. 공장은 실제로 로케이터처럼 냄새가 아니며, 속한 도메인의 일부인 로컬 팩토리입니다.

단계는 공장 제품군 (인터페이스)에 대한 아이디어를 잊어 버리고 컨테이너를 내부적으로 사용하는 (또는 사용하지 않는) 플러그 가능 구현이있는 구체적인 팩토리를 갖지만 해당 컨테이너에 대해 단일 API를 제공합니다. 고객. 이 방법을 사용하면 factory의 constructor 주입을 form에 제거하여 factory의 concrete 유형을 사용하는 것이 가능합니다. 공장 자체는 Composition Root에서 구성됩니다. 내 블로그 항목

http://www.wiktorzychla.com/2016/01/di-factories-and-composition-root.html

0

첫 번째 예에서

자세한 내용 및 코드 예제 : 당신은 또한 의존 할 수없는 단위 테스트를 가지고 있기 때문에 나는 좋아하지 않는다. 그것은 ChildWindow의 인스턴스를 해결할 수 없으며 제어 할 수 없습니다.

두 번째 예 : 클래스 컨테이너이 아니기 때문에 인터페이스가 좋지 않습니다.

세 번째 예 : 예전보다 잘 작동하며 때로는 그런 식으로 공장을 사용합니다. 그것은 완벽하게 단위 테스트를 할 수 있습니다.

보통 DI 컨테이너는 공장과 같이 더 많은 기능을 제공하기 때문에 공장으로 사용하는 것이 더 좋습니다. 개체 수명 ...

나는 결코 클래스 ChildWindow을 사용하지 않았다. 그러나 생성자 인터페이스에서 정의 할 수 없으면 차라리 ChildWindowWrapper : IChildWindowWrapper를 구현하고 랩퍼를 사용한다. 그것은 단위 테스트를 단순하게 할 것이며 DI 컨테이너에서 사용될 수 있습니다.

+0

"DI 컨테이너를 공장으로 사용"및 "ChildWindowWrapper" – LeY

+0

@LeY의 예를 제공 할 수 있습니까? 소리가 분명한 경우 죄송합니다. 공장 패턴 (방법)을 사용하는 대신 오브젝트의 새로운 인스턴스를 생성하기 위해 DI 컨테이너를 사용하겠다고 말하고 싶습니다. 예를 들어, class가 Interface 나 Abstract 클래스를 구현하지 않으면 wrapper 클래스를 사용할 것입니다. Wrapper는 필요한 특정 기능을 캡슐화하는 클래스입니다. 대신 클래스에서 코드를 직접 사용하여 Wrapper를 직접 사용해야합니다. 래퍼는 인터페이스를 구현해야하며 DI 컨테이너에 등록 할 수 있습니다. – kat1330