24

나는 일하고있는 애완 동물 프로젝트에 윈저 성을 사용하고 있습니다. 새로운 객체를 만들기 위해 다른 곳에서 IoC 컨테이너를 호출해야한다는 것을 알기 시작했습니다. 이 컨테이너에 대한 의존성으로 인해 코드를 유지하기가 더 어려워집니다.IoC, 컨테이너를 어디에 두겠습니까?

내가 내가 객체를 생성 할 필요가 내 응용 프로그램의 부분으로 주입 할 수있는 용기 래퍼 추상적 공장을 만들려고이 문제

를 해결하기 위해 사용했습니다 두 가지 해결책이 있습니다. 성은 의존성으로 자신의 컨테이너를 주입하기가 어렵 기 때문에 이것은 작동하지만 결점이 있습니다. 그래서 저는 이것을 손으로해야만합니다, 이런 종류의 IoC 컨테이너의 모든 목적을 이겨내십시오.

저는 주 applicationcontroller 클래스를 사용하여 IoC 컨테이너를 랩하고 중앙 공장/저장소로 작동했습니다. 이것은 꽤 성공적 이었지만이 수업은 너무 커져서 중앙 신 개체처럼 작동합니다. 거의 모든 다른 객체에는이 객체에 대한 참조가 있습니다.

두 가지 솔루션은 일종의 작업이지만 둘 다 단점이 있습니다. 그래서 다른 사람들이 같은 문제를 가지고 더 나은 해결책을 찾았다면 궁금합니다.


편집 문제는 여기에 객체 B.에 따라 나는 보통 단지 생성자 주입을 사용하고 모든 작품 객체 A에 대해이 아니다. 때로는 유형 A의 오브젝트가 있는데,이 오브젝트는 수명 동안 B 유형의 다른 오브젝트를 가변적으로 작성해야합니다. 어떻게해야할지 모르겠습니다.

@Blair Conrad : 유지 관리 문제는 지금까지 심각하지 않습니다. 일부 클래스는 컨테이너 객체 호출 container.Resolve <>에 의존합니다. 그리고 저는 인프라라고 생각하는 것에 따라 제 코드를 갖고 싶지 않습니다. 여전히 프로젝트를 시도하고 있는데,이 프로젝트에서 ninject에서 성으로 전환 할 때 많은 코드를 변경해야한다는 것을 알게되었습니다.

@flowers : Hmm. 나는 당신의 주먹 해결책을 좋아한다. 그것은 내가 시도한 두 가지 솔루션에서 작동하는 것들을 결합합니다. 나는 여전히 객체에 너무 많은 것을 생각하고 있으며 인터페이스/책임이 충분하지 않다고 생각한다. 목적으로 만들어진 공장을 시험해 보았습니다.하지만 나는 그 물건을 만들기 위해 뒤에서 컨테이너를 사용하고 싶습니다. 그리고 나는 어떻게 컨테이너를 깨끗한 방법으로 물건을 넣을 수 있는지 알지 못했습니다.

+0

저는 궁금해서 답변이 도움이 될 수 있습니다. 어떤 종류의 유지 보수 문제가 있습니까? –

답변

3

적어도 내 응용 프로그램에서 종속성 주입의 주요 이점은 상황에 구애받지 않는 코드를 작성하는 것입니다. 그런 관점에서 볼 때, 두 번째 해결책은 DI가 당신에게 줄 수있는 이익을 실제로 훼손시키는 것처럼 보입니다. '신 오브젝트'가 인터페이스를 참조하는 각 클래스에 대해 다른 인터페이스를 노출하면 너무 위험하지 않을 수 있습니다. 그러나 당신이 그렇게 멀리 간다면 나는 왜 당신이 후프까지 그것을 가져 가지 않았는지 알지 못합니다.

예 : 사용자의 God 객체에는 getFoo() 메소드와 getBar() 메소드가 있습니다. 객체 A에는 Foo가 필요하고 객체 B에는 Bar가 필요합니다. A가 Foo를 하나만 필요로한다면, Foo는 A에 직접 주입되어야하고 A는 전혀 신을 인식하지 않아야합니다. 그러나 A가 Foos를 계속 만들어야 할 필요가 있다면 A에게 하나님에 대한 언급을하는 것은 거의 불가피합니다. 그러나 하나님에 대한 언급의 유형을 좁힘으로써 하나님을 지나쳐 버린 피해로부터 자신을 보호 할 수 있습니다. 하나님이 FooFactory를 구현하게하고 A에게 하나님이 구현 한 FooFactory에 대한 참조를 주면 A에서 문맥 중립적 인 방식으로 코드를 작성할 수 있습니다. 이렇게하면 코드 재사용의 기회가 향상되고 신의 변화로 인해 예상치 못한 부작용이 발생하지 않는다는 자신감이 높아집니다. 예를 들어 클래스 A가 중단되지 않는 getBar()를 God에서 제거 할 때 확실 할 수 있습니다.

하지만 ...어쨌든 모든 인터페이스를 갖게된다면, 컨테이너를 포장하는 것이 아니라 공장 내에 포함 된 팩토리를 함께 모으는 것이 좋습니다. 컨테이너는 여전히 팩토리를 구성 할 수 있습니다.

2

공개 된 인터페이스 (작은 "i")가 새 공장 및/또는 새 건물에서 계속 변하기 때문에 "목적으로 만들어진 공장"에 대한 설명을 듣고 직접 사용해도 좋습니다. 각 구현에 대해 새로운 GetX 메소드. 제레미 밀러 (Jeremy Miller)의 It's time for IoC Container Detente을 읽은 후 제네릭을 의심하고 용기를 주입하는 것이 최선의 방법입니다.

Jeremy의 기사에서 제안 된 것과 같은 일종의 IServiceLocator 인터페이스에서 Ninject, StructureMap 또는 Windsor를 감쌀 것입니다. 그런 다음 원래의 제안처럼 루프 내에서도 IServiceLocator를 코드의 아무 곳이나 반환하는 컨테이너 팩토리를 보유하십시오.

IServiceLocator container = ContainerFactory.GetContainer(); 
while(keepLooping) 
{ 
    IExample example = container.GetInstance<IExample>(); 
    keepLooping = example.DoWork(); 
} 

컨테이너 공장은 항상 당신이 무엇을 IOC의 프레임 워크를 교체 할 수 있습니다, 같은 intance를 반환 할 수 있습니다.

11

IoC.Container.Resolve 또는 ContainerFactory.GetContainer와 같은 정적 클래스를 사용하지 마십시오.

이렇게하면 코드가 복잡해지고 유지 관리, 재사용 및 읽기가 더 어려워집니다.

일반적으로 단일 구성 요소 또는 서비스에는 단일 주입 지점 만 있습니다. 이는 구성 속성 (선택 사항 속성 포함)입니다. 그리고 일반적으로 구성 요소 또는 서비스 클래스는 컨테이너와 같은 것의 존재를 알지 못합니다. 당신의 구성 요소가 정말 (즉, 이름에 따라, 예외 처리 정책이나 워크 플로우를 해결하는) 내부의 동적 해상도가해야 할 경우 @flipdoubt

만약 후속으로

은, 그때 lending IoC powers via the highly-specific providers

+0

링크를 제공해 주셔서 감사합니다. 나는 시간이있을 때 좀 더 캐 러시 글을 읽어야하지만, 나는 그와 비슷한 것을 시도해 본 다음에 반대하여 IoC 컨테이너를 사용하는 대신에 동적 인 객체를 생성하기 위해 추상 팩토리를 사용했다고 생각한다. 컨테이너 만 사용하여 팩토리를 만들었습니다. – Mendelt

+2

@Rinat, OP의 원래 시나리오 사용 : A에 있고 n 개의 B 인스턴스가 필요합니다. 컨테이너에 대한 언급이 없으면 어떻게 Bs를 얻을 수 있습니까? – flipdoubt

+0

귀하의 링크가 작동하지 않습니다 ... 당신이 그것을 업데이트 할 수 있습니까? –

1

을 고려하는 것이 좋습니다 당신은 http://www.codeplex.com/CommonServiceLocator을 체크 아웃하고자하는 서비스 로케이터 유형 패턴을 사용하여 끝낼 수 있습니다. 도움이 될만한 몇 가지 유명한 IoC 프레임 워크 (windsor, structuremap)에서 사용할 수있는 바인딩이 있습니다.

행운을 빈다.

+0

감사! 나는 그것을 조사 할 것이다. 나는 당신 자신의 서비스 검색자를 만드는 것이 쉽다는 것을 알았지 만, 나는 그들이 어떻게 한 일을했는지에 대한 아이디어를 얻을 수있다! – Mendelt

+0

걱정하지 마세요. 행운을 빈다. – smaclell

1

필자가 언급 한 것처럼 강력하게 입력 된 공장을 사용하는 것이 좋습니다. 그러한 팩토리는 컨테이너를 랩 할 수 있습니다 만, 추가의 문맥으로 패스 해, 여분의 처리를 실시 할 수가 있습니다. 예를 들어 OrderFactory의 Create는 컨텍스트 매개 변수를 받아 들일 수 있습니다.

일반 서비스 로케이터에 대한 정적 종속성은 의도와 컨텍스트가 느슨해 지므로 좋지 않은 아이디어입니다. IoC가 인스턴스를 빌드하면 큰 그림이있는 것처럼 proifle, context 등과 같은 여러 요소를 기반으로 올바른 종속성을 제공 할 수 있습니다.

CommonServiceLocator는이 용도로 사용하지 않지만 유혹을 불러 일으킬 수 있습니다. CommonServiceLocator의 주요 목적은 IoC 컨테이너를 준수하도록하려는 앱/프레임 워크를위한 것입니다. 그러나 사용하는 앱은 구성 요소 및 해당 종속 구성 요소의 계층을 구축하기 위해 한 번만 최적으로 로케이터를 호출해야합니다. 다시는 직접 호출해서는 안됩니다. 우리가 할 수있는 방법을 강구한다면 Prism (http://www.microsoft.com/compositewpf)에서는 모듈을 만들기위한 IContainerFacade를 도입했습니다. 저급 수준이지만 서비스 로케이터입니다. 되돌아 보면 우리는 아마도 ModuleFactory 나 뭔가를 생성하고 IContianerFacade를 사용하여 그것을 잡아야하고 그 다음에 그 모듈을 사용하여 Facade에 직접 갈 것입니다. 뒤늦은 지경은 20 분의 20입니다.그것은 사물에 실제로 영향을 미치지는 않지만 충분히 낮은 수준입니다.

CSL에서는 혼동을 초래할 수 있으므로 이름을 지어 냈습니다. 결국 기술적으로 인터페이스가 DI를 수행하지 않았기 때문에 CSL을 결정했습니다.

10

Nick Blumhardt의 미니 시리즈를 확인하는 것이 좋습니다. 정말 comon 문제입니다

http://blogs.msdn.com/nblumhardt/archive/2008/12/27/container-managed-application-design-prelude-where-does-the-container-belong.aspx

+0

감사합니다! 내 독서 목록에 추가했습니다 :-) – Mendelt

+0

이것은 훌륭한 기사 였고 저를 위해이 문제를 명확히하는 데 도움이되었습니다! –

+0

링크를 마음에 들어했습니다. 그러나 나는 또한 단순한 링크가 아닌 높은 수준의 여름을 선호합니다. – KFL

0

. 윈저의 Typed Factory Facility 내장은 언급 된 단점없이 공장 사용의 이점을 제공합니다.

관련 문제