1

StructureMap의 사용법을 이해하는 데 어려움을 겪고 있습니다. 대신생성자 삽입과 서비스 로케이터 사용시기

public ShippingScreenPresenter() 
    { 
     _service = ObjectFactory.GetInstance<IShippingService>(); 
     _repository = ObjectFactory.GetInstance<IRepository>(); 
    } 

: 특히 는 문서의 문장은 일반적인 안티 패턴의 서비스 로케이터로 StructureMap의 용도로만 사용하는 대신 생성자 주입 (직선 Structuremap 문서에서 코드 샘플)에 대한 구성되어 있습니다

public ShippingScreenPresenter(IShippingService service, IRepository repository) 
    { 
     _service = service; 
     _repository = repository; 
    } 

이 매우 짧은 개체 그래프에 대한 괜찮지 만, 많은 수준 깊은 객체를 처리 할 때, 이것이 바로 정상에서 깊은 객체에 필요한 모든 종속성을 통과해야한다는 의미는 무엇입니까? 확실히 이것은 캡슐화를 깨고 더 깊은 객체의 구현에 대해 너무 많은 정보를 노출합니다.

활성 레코드 패턴을 사용하고있어 내 레코드가 데이터 리포지토리에 액세스하여 자신을 저장하고로드 할 수 있어야한다고 가정 해 봅시다. 이 레코드가 객체 안에로드되면 해당 객체는 ObjectFactory.CreateInstance()를 호출하여 활성 레코드의 생성자에 전달합니까? 그 객체가 다른 객체 안에 있다면? IRepository를 자체 매개 변수로 사용합니다. 이것은 부모 객체에 우리가이 시점에서 데이터 저장소에 액세스한다는 사실을 나타냅니다. 외부 객체는 아마도 알 수 없습니다.

public class OuterClass 
{ 
    public OuterClass(IRepository repository) 
    { 
     // Why should I know that ThingThatNeedsRecord needs a repository? 
     // that smells like exposed implementation to me, especially since 
     // ThingThatNeedsRecord doesn't use the repo itself, but passes it 
     // to the record. 
     // Also where do I create repository? Have to instantiate it somewhere 
     // up the chain of objects 
     ThingThatNeedsRecord thing = new ThingThatNeedsRecord(repository); 
     thing.GetAnswer("question"); 
    } 
} 

public class ThingThatNeedsRecord 
{ 
    public ThingThatNeedsRecord(IRepository repository) 
    { 
     this.repository = repository; 
    } 

    public string GetAnswer(string someParam) 
    { 
     // create activeRecord(s) and process, returning some result 
     // part of which contains: 
     ActiveRecord record = new ActiveRecord(repository, key); 
    } 

    private IRepository repository; 
} 

public class ActiveRecord 
{ 
    public ActiveRecord(IRepository repository) 
    { 
     this.repository = repository; 
    } 

    public ActiveRecord(IRepository repository, int primaryKey); 
    { 
     this.repositry = repository; 
     Load(primaryKey); 
    } 

    public void Save(); 

    private void Load(int primaryKey) 
    { 
     this.primaryKey = primaryKey; 
     // access the database via the repository and set someData 
    } 

    private IRepository repository; 
    private int primaryKey; 
    private string someData; 
} 

모든 의견을 환영합니다.

사이먼

편집 : 의견 주입 상단 계층에서 시작해야 함을 보인다. ActiveRecord는 OuterClass에 삽입 된 ThingThatNeedsRecord에 주입됩니다. 이 문제는 ActiveRecord를 런타임 매개 변수 (예 : 검색 할 레코드의 ID)로 인스턴스화해야하는 경우에 발생합니다. 상단에있는 ThingThatNeedsRecord에 ActiveRecord를 주입한다면 어떻게 든 그 위치에 있어야하는 ID를 알아 내야 만합니다 (상단 레이어를 구현하지 않아야 함). 그렇지 않으면 부분적으로 생성 된 ActiveRecord가 있어야합니다. 나중에 이드를 설정하십시오. 이것은 N 개의 레코드가 필요하고 ThingThatNeedsRecord 내부에서 로직을 실행할 때까지 알지 못한다면 더 복잡해집니다.

+0

가능한 복제본 : http://stackoverflow.com/questions/4570750/dependency-injection-turtles-all-the-way-down –

+0

관련 항목 : http://stackoverflow.com/questions/2420193/dependency-injection- 생성자 - 광기/2420245 # 2420245 –

답변

6

통제 반전은 폭력과 같습니다. 문제가 해결되지 않으면 충분하지 않습니다. 또는 something like that.

더 많은 점은 당신의 OuterClass은 생성자 주입을 통해 ThingThatNeedsRecord을 주입해야한다고 생각합니다. 마찬가지로 ThingThatNeedsRecord에는 ActiveRecord이 주입되어야합니다. 이 방법은 즉각적인 문제를 해결할뿐만 아니라 코드를 모듈화하고 테스트 할 수있게 해줍니다.

+0

나는 원래의 우려로 돌아 간다고 생각합니다. OuterClass 위에 ThingThatNeedsRecord를 만들고 ActiveRecord를 삽입하면 OuterClass 위의 객체는 객체 그래프에서 ThingThatNeedsRecord 방법의 내부 구현에 노출됩니다. – Simon

+0

(StructureMap) 컨테이너를 통해 OuterClass를 생성하는 경우, OuterClass를 사용하는 코드는 ThingThatNeedsRecord 의존성에 노출되지 않습니다. 적절하게 설정되면, 컨테이너는'OuterClass'에'ThingThatNeedsRecord'를 제공 할뿐만 아니라 객체 그래프의 다른 의존성을 재귀 적으로 처리합니다. –

+1

궁극적으로 최상위 레벨에서는 ObjectFactory에서 오브젝트를 가져 오는 서비스 위치 호출이있게됩니다. 그러나 해당 객체의 종속성 (및 종속성)은 모두 컨테이너에서 만족하므로 서비스 위치 호출을 수행하는 코드는 이러한 종속성에 대해 알 필요가 없습니다. –