2014-11-17 2 views
2

Windows 서비스의 IoC 프레임 워크로 Ninject를 사용하려고합니다.구성에 따라 다른 인스턴스 확인

총회 코어 :

public class Orchestrator : IOrchestrator 
{ 
    ... 

    public Orchestrator(ITerminal terminal) 
    { 
     ... 
    } 

    ... 
} 

조립 Vx520 :

public class Vx520 : ITerminal 
{ 
    ... 

    public Vx520(string comPort, int bauds, int dataBits, Parity parity, StopBits stopBits) 
    { 
     ... 
    } 

    ... 
} 

조립 Vx580 :

public class Vx580 : ITerminal 
{ 
    ... 

    public Vx580(string ip, int port) 
    { 
     ... 
    } 

    ... 
} 

내 생각은 ConfigurationSection를 사용하는 것입니다 나는 다음과 같은 클래스와 인터페이스가 사용자가 단말기 수와 단말기 수를 구성 할 수있게합니다. 그는 원한다. 로,

<Terminals> 
    <add Type="Vx520" ComPort="COM3" Bauds="9600" DataBits="8" Parity="None" StopBits="One" /> 
    <add Type="Vx580" Ip="192.168.0.50" Port="33999"/> 
    <add Type="Vx580" Ip="192.168.0.51" Port="33999"/> 
</Terminals> 

내가 구성 부분의 작업이 예를 들어, 다음과 같은 구성에서, 나는 그것으로 각 사용자 정의 구성의 3 개 Orcestrator 인스턴스하는 Vx520 터미널 하나, 그리고 Vx580와 다른 두를 얻어야한다 IEnumerable<TerminalConfiguration>을 최종 출력으로 사용합니다. 이 구성 목록을 사용하여 Orchestrator 클래스의 종속성을 동적으로 해결할 수 있습니까? Ninject가이 작업을 수행 할 수없는 경우 나에게 추천 할 수있는 다른 IoC 프레임 워크가 있습니까?

사전

+0

"Orchestrator"에 어떤 것을 넣고 싶습니까? 당신은 무엇을 기반으로 결정합니까? –

+0

@YuvalItzchakov'TerminalConfiguration'의 목록을 기반으로합니다. 그 목록에 3 개의 항목이 있다고 가정하면, 구성의'Type' 필드를 기반으로 한 터미널 중 하나를 사용하여 각각 3 개의 Orchestrator를 원합니다. –

답변

1

Ninject에 (또는 대부분 또는 그 문제에 대한, 심지어 모든 DI 컨테이너가) 어떤 임의의 "외부"정보를 기반으로 인스턴스화하는 데 얼마나 많은 개체를 제어하는 ​​데 사용할 수 없습니다에 감사드립니다.

IBindingRoot.Bind<IOrchestrator>().To<Orchestrator>(); 
IBindingRoot.Bind<IOrchestrator>().To<Orchestrator>(); 
IBindingRoot.Bind<IOrchestrator>().To<Orchestrator>(); 

을 한 다음 (유형 IEnumerable<IOrchestrator>의 ctor에 인수를 주입 또는 IResolutionRoot.GetAll<IOrchestrator>()별로 검색 그게 정확히 3 경우에 발생합니다 을 또한 조건부 가질 수 있습니다.. 당신은 여러 바인딩을 가지고있다 할과 같이 할 수있는 작업 (문맥)은 예를 들어, 바인딩에 조건을 넣어 바인딩 :

IBindingRoot.Bind<ITerminal>().To<Vx520>() 
    .When(x => Config.Terminal.Type == "VX520"); 
IBindingRoot.Bind<ITerminal>().To<Vx580>() 
    .When(x => Config.Terminal.Type == "VX580"); 

을하고 당신은 ITerminal/당신이 얻을 것이다 IResolutionRoot.Get<ITerminal>() 않는 Vx520 또는 Vx580 (또는 누락 바인딩 excepti를 주입 할 때 on!) 값에 따라 Config.Terminal.Type.

지금, 물론, 당신은 설정을 구문 분석 할 수 있으며, 그에 따라 바인딩을 만들 :
foreach(ITerminalConfig config in Terminals) 
{ 
    IBindingRoot.Bind<IOrchestrator>().To<Orchestrator>() 
     .WithParameter(new ConstructorArgument("config", config, shouldInherit: true)); 
} 

그래서 당신이 설정의 보유 ConstructorArgumentIOrchestrator, 각각 3 바인딩을 가질 것이다. ConstructorArgumentshouldInherit이 true로 설정되어 있으므로 IOrchestrator 트리 아래 유형을 주입 할 수 있으며 조건을 주입 할 수도 있습니다. (즉, 당신이 IP & 포트/처신 & 전송 속도 .. 설정을 얻을 것입니다 방법)

IBindingRoot.Bind<ITerminal>().To<Vx580>() 
    .When(ctx => 
    { 
     ConstructorArgument configConstructorArgument = 
      ctx.Parameters 
       .OfType<ConstructorArgument>() 
       .Single(x => x.Name == "config"); 

     var config = (ITerminalConfig)configConstructorArgument.GetValue(null, null); 
     return config.Type == "Vx520"; 
    }); 

또한 Vx520에 주입 된 ITerminalConfig이 예를 들어, 당신의 라인을 따라 뭔가를 할 수 있습니다.


그러나

는 작성이 명시 적으로 수행해야하는 더 나은되지 않을 것 대신에 여러 Bind<IOrchestrator>().To<Orchestrator>() 바인딩을 만드는, 정직합니까? IOrchestratorFactory을 사용하여 인스턴스를 만드는 일부 서비스 초기화 프로그램/응용 프로그램 시작 단계마다?

+0

답장을 보내 주셔서 감사합니다. 마지막 코드 스 니펫을 삽입 할 터미널을 선택하고'Orchestrator's를'configuration.Terminals.Select (config => kernel.Get (새로운 ConfigructorArgument ("config", config , true)))' –

관련 문제