2016-06-21 5 views
0

그래서 나는이 응용 프로그램에서 IOC (autofac)를 사용하고 있습니다. 그때 나는 공장이 필요한 위치에 자리 잡고있었습니다. 공장 내에서는 의존성이있는 새로운 객체를 만듭니다. 그래서 지금 궁금합니다. 어떻게 이들과 결혼 할 수 있습니까?공장 및 IOC 함께 - 둘 다 어떻게 사용합니까?

public class SubscriptionHandlerFactory : ISubscriptionHandlerFactory 
{ 
    public ISubscriptionHandler GetProvider(StreamType streamType) 
    { 
     switch (streamType) 
     { 
      case StreamType.Rss: 
       return new RssSubscriptionHandler(null,null,null,null); 
      case StreamType.Person: 
       return new PersonSubscriptionHandler(null, null, null, null); 
      default: 
       throw new ArgumentOutOfRangeException(nameof(streamType), streamType, null); 
     } 
    } 
} 
+1

공장에 IoC 컨테이너를 주입 한 후 당신이 원하는 구체적인 유형의 인스턴스를 얻기 위해 그것에 노출 된 메서드를 사용하십시오. 그런 다음 컨테이너가 다른 종속성을 해결합니다. –

+0

@MartinCostello는 서비스 위치 지정 자입니다. 공장 내에서 이루어 지더라도 대부분 안티 패턴으로 간주됩니다. –

+0

당신은 공장이 필요하다고 확신합니까? IoC 컨테이너가 개체 종속성 그래프를 작성할 수 없도록하는 이유는 무엇입니까? –

답변

1

당신은 named and keyed service을 사용하여 다음과 같이 할 수 IIndex<TKey, TService>

등록을 사용하여 인스턴스를 검색 할 수 있습니다 :

이 같은
builder.RegisterType<RssHandler>().Keyed<ISubscriptionHandler>(StreamType.Rss); 
builder.RegisterType<PersonHandler>().Keyed<ISubscriptionHandler>(StreamType.Person); 
builder.RegisterType<SubscriptionHandlerFactory>().As<ISubscriptionHandlerFactory>(); 

및 공장 :

public class SubscriptionHandlerFactory : ISubscriptionHandlerFactory 
{ 
    public SubscriptionHandlerFactory(IIndex<StreamType, ISubscriptionHandler> handlers) 
    { 
     this._handlers = handlers; 
    } 

    private readonly IIndex<StreamType, ISubscriptionHandler> _handlers; 

    public ISubscriptionHandler GetProvider(StreamType streamType) 
    { 
     return this._handlers[streamType]; 
    } 
} 
+0

이것은 굉장합니다. 또한 자동 캡슐에 부착되지 않기 위해 IIndex를 추상화 할 수 있습니다. – jstadnicki

+0

실제로 공장은 그 공장 고객의 관점에서 자동 팩보다 추상화되었습니다. – jstadnicki

0

IoC를 사용하여 개체의 인스턴스 생성을 영원히 추상화 할 수는 없습니다. 어느 시점에서 구체 인스턴스 (공장 또는 IoC 컨테이너 내부)를 만들어야합니다.

공장에 autofac 컨테이너를 삽입하거나 공장 자체가 인터페이스를 구현할 수 있으므로 (예 : 단위 테스트 목적으로 다른 공장이 필요한 경우)

0

해결할 수 있습니다. 거의. 내가 Autofac에 의존하고 싶지 않았기 때문에 나는 스스로 찢겼다. 하지만 @ martin-costello 덕택에 autofac을 사용할 필요가 없을 수도 있지만 IDependencyResolver를 빌드하는 것이 덜 위험합니다. autofac을 IDependencyResolver로 등록 할 수 없어서 DependencyResolver를 IDependencyResolver로 등록합니다. 한 걸음 더 가까이. Autofac DependencyResolver.SetResolver가 발생하기 전에 등록이 발생하기 때문에 Lazy를 사용하여 마침내 내 문제를 해결해야했습니다.

여기

// other registration 
builder.RegisterType<RssSubscriptionHandler>(); 
builder.RegisterType<PersonSubscriptionHandler>(); 
// even more registration here 

builder.RegisterType<SubscriptionHandlerFactory>() 
     .As<ISubscriptionHandlerFactory>() 
     .WithParameter(new TypedParameter(typeof(Lazy<IDependencyResolver>), 
         new Lazy<IDependencyResolver>(() => DependencyResolver.Current))); 
이 (전에 정리)에 그런 공장 변경

코드 (또는 적어도 최선의 해결책 내가 발견)입니다 : 지금은

public class SubscriptionHandlerFactory : ISubscriptionHandlerFactory 
{ 
    private readonly Lazy<IDependencyResolver> resolver; 

    public SubscriptionHandlerFactory(Lazy<IDependencyResolver> resolver) 
    { 
     this.resolver = resolver; 
    } 

    public ISubscriptionHandler GetProvider(StreamType streamType) 
    { 
     switch (streamType) 
     { 
      case StreamType.Rss: 
       return (ISubscriptionHandler)this.resolver.Value.GetService(typeof(RssSubscriptionHandler)); 
      case StreamType.Person: 
       return (ISubscriptionHandler)this.resolver.Value.GetService(typeof(PersonSubscriptionHandler)); 
      default: 
       throw new ArgumentOutOfRangeException(nameof(streamType), streamType, null); 
     } 
    } 
} 

이 최고의/깨끗한/덜 악한/덜 구체화 된/추상적/어떤 솔루션을 내가 알아낼 수 있었다. 모든 의견 환영.