2012-04-19 1 views
0

호출중인 작업의 매개 변수 값에 의존하는 종속성을 해결하려고합니다.구조체 맵의 매개 변수에 따라 구체적인 유형을 확인하십시오.

나는 나는 또한 나의 용기 내 ValueProvider 두 가지 구체적인 유형의 등록이 WCF 서비스를

public class InformationService : IInformationService 
{ 
    private readonly IValueProvider _valueProvider; 

    public InformationService(IValueProvider valueProvider) 
    { 
     _valueProvider= valueProvider; 
    } 


    public CompanyReportResponse CompanyReport(string option) 
    { 
     _valueProvider.Execute(option); 
    } 
} 

있습니다.

Registry.For<IValueProvider>().Add<ValueProvider1>().Named("No1"); 
Registry.For<IValueProvider>().Add<ValueProvider2>().Named("No2"); 

옵션 값에 따라 다른 값 제공 업체를 사용할 수 있습니까?

즉, 옵션은 "value1" 다음 _valueProvider 콘크리트 유형 ValueProvider1를 사용하고 옵션 "value2 때 "다음 _valueProvider 콘크리트 유형 ValueProvider2을 사용합니다.

답변

2

을 나는 적어도 2 개의 다른 옵션을 참조하십시오.

하면 때 ValueProvider은 그 메소드에서만 사용됩니다. 메소드 삽입을 고려할 수 있습니다. option 인수를 전달할 때 어떤 메소드가 사용되는지 이미 알고 있으므로 추가 인수로 사용할 IValueProvider 구현을 제공 할 수 있습니다.

public CompanyReportResponse CompanyReport(string option, IValueProvider provider) 
{ 
    _provider.Execute(option); 
} 
두 번째 옵션은 ValueProvider를 빌드하는 팩터 리를 정의하고 생성자 주입을 통해이 팩토리를 주입하는 것입니다. 팩토리에는 option 인수에 따라 올바른 ValueProvider를 인스턴스화하는 메소드가 있습니다.

public interface IValueProviderFactory 
{ 
    IValueProvider CreateProvider(string option); 
} 

public class ValueProviderFactory : IValueProviderFactory 
{ 
    public IValueProvider CreateProvider(string option) 
    { 
     // Insert custom instantiation logic here: 
     // if option == "value1" return ValueProvider1 and so on 
    } 
} 

public class InformationService : IInformationService 
{ 
    private readonly IValueProviderFactory _valueProviderFactory; 

    public InformationService(IValueProviderFactory valueProviderFactory) 
    { 
     _valueProviderFactory = valueProviderFactory; 
    } 

    public CompanyReportResponse CompanyReport(string option) 
    { 
     var valueProvider = _valueProviderFactory.CreateProvider(option); 
     valueProvider.Execute(option); 
    } 
} 
+0

이것은 InformationService에서 개인 메소드를 처음 작성한 이후 처음으로 솔루션을 생각한 것과 매우 흡사합니다. 이제는 별도의 팩토리를 두 ​​번째 솔루션으로 사용하도록 변경했지만 컨테이너에서 정확한 콘크리트 유형을 검색하기 위해'GetInstance'를 사용합니다. – Per

2

+1 @ filpen 's answer. 세 번째 옵션을 추가하고 싶습니다.

public SwitchingValueProviderProxy: IValueProvider 
{ 
    private readonly ValueProvider1 provider1; 
    private readonly ValueProvider2 provider2; 

    public SwitchingValueProviderProxy(
     ValueProvider1 provider1, 
     ValueProvider2 provider2) 
    { 
     this.provider1 = provider1; 
     this.provider2 = provider2; 
    } 

    void IValueProvider.Execute(option option) 
    { 
     this.GetProvider(option).Execute(option); 
    } 

    private IValueProvider GetProvider(string option) 
    { 
     // custom instance logic here 
     if (option.EndsWith("1")) 
      return this.provider1; 

     if (option.EndsWith("2")) 
      return this.provider2; 

     throw InvalidOperationException(); 
    } 
} 

이 몇 가지 분명한 장점이 있습니다 대신 공장을 주입 또는 컨텍스트 기반의 주입을하고, 당신은 올바른 구현에 위임 프록시를 도입 할 수 있습니다. 무엇보다 먼저 클라이언트에서 실행할 공급자를 결정하는 논리와 논리를 완전히 숨 깁니다. 클라이언트는 이제 IValueProvider 인터페이스에만 의존합니다. 다음 구성은 현재 매우 깨끗해졌습니다.

Registry.For<IValueProvider>() 
    .Add<SwitchingValueProviderProxy>(); 

그게 전부입니다. 선택 논리를 IValueProviderFactory으로 추출하여 SwitchingValueProviderProxy에 삽입 할 수 있다면이 클래스를 간단하고 집중적으로 유지하면서 나머지 응용 프로그램을 공장에 대해 무지하게 유지할 수 있습니다.

+0

+1. IValueProvider를 구현 한 뒤에 숨겨진 방법은 흥미 롭습니다.하지만 IValueProvider가 변경 될 때마다 프록시를 변경해야합니다. SRP에 비추어 볼 때 클래스에는 두 가지 책임이 있습니다. 즉, 구현 (프록시)으로 호출을 전달하고 올바른 클래스 (팩토리)를 인스턴스화해야하므로이 솔루션에 비해 확실하지 않습니다. 팩토리 하나, 2가 아닌 1 추상화에 따라 클라이언트 옆에 있습니다. 이는 문제 일 수도 있고 아닐 수도 있습니다. –

+0

@filpen : 일을 단순하게하고 싶었지만 당신이 옳다면 공장이 SRP를 준수해야합니다. 여전히 새로운 가치 제공 업체를 추가한다는 것은 프록시 또는 공장을 변경해야한다는 것을 의미합니다.클라이언트가 'IValueProvider'에만 의존하게되면 공장에 의존하는 것보다 더 깔끔합니다. 그러나 고객이 공장에 의존 할 때 실제로 '문제'는 없습니다. 코드가 조금 더 깨끗해 지므로 단위 테스트도 수행하십시오. – Steven

관련 문제