2014-07-17 2 views
0

인터페이스가 있으므로 IConfig라고 부르 자. 다음으로 클래스 러너가 있습니다. Runner는 생성자에서 IConfig와 다른 매개 변수를 사용합니다.작업 및 Ninject를 사용하여 병렬 처리

하지만 ActivationException이 발생하여 둘 이상의 IConfig 인스턴스가 각각 실행을 정의 할 때 주자를 GetAll 할 수 없습니다. "두 개 이상의 일치하는 바인딩을 사용할 수 있습니다."

이것이 표준 커널이 작동하는 방식이 아니기 때문에 이것이라고 생각합니다. 내가 원하는 것은 커널이 바인딩 된 각 IConfig에 대해 Runner의 새로운 인스턴스를 생성하는 것입니다.

수동으로 인스턴스를 만들지 않고도 ninject를 사용하여이 작업을 수행 할 수 있습니까? 내가 원하는 것을

예제 코드 : 내가 대신해야 할 일의

Task.WaitAll(kernel.GetAll<IRunner>().Select(r => Task.Run((Action)r.Run)).ToArray()); 

예제 코드 : 이와 같은 시나리오에 대한 기본 지원에는 밖으로이 없습니다

IControl control = kernel.Get<IControl>(); 
Task[] runners = kernel.GetAll<IConfig>() 
    .Select(c => new Runner(kernel.Get<IService1>(), kernel.Get<IService2>(), c, control)) 
    .Select(r => Task.Run((Action)r.Run)) 
    .ToArray(); 
Task.WaitAll(runners); 

답변

2

. 원하는 것을 성취 할 수있는 방법은 다양합니다.

그럼

public class Runner 
{ 
    public Runner(IService1 service1, IService2 service2, IConfig config, IControl control) 
    { 
    } 

    public void Run() 
    { 
    } 
} 

해결 방법 1 시작하자 : - 의존성 삽입 (Dependency Injection)을 특징으로 을 우리는 주자를 만들 바인딩 .ToFactory()을 사용하는 것입니다.

public interface IRunnerFactory 
{ 
    // all parameters are passed to the constructor of Runner 
    // parameters are matched by name, so make sure they match! ctor(IConfig myconfig) won't work, it must be ctor(IConfig config). 
    // but of course you can add more parameters to the ctor and have them injected: ctor(IService1 foo, IControl bar, IConfig config, IService2 foo2) 
    Runner Create(IConfig config); 
} 

public class AllRunner 
{ 
    private readonly IList<IConfig> runnerConfigurations; 
    private readonly IRunnerFactory runnerFactory; 

    public AllRunner(IList<IConfig> runnerConfigurations, IRunnerFactory runnerFactory) 
    { 
     this.runnerConfigurations = runnerConfigurations; 
     this.runnerFactory = runnerFactory; 
    } 

    public void RunAll() 
    { 
     Task[] runners = this.runnerConfigurations 
      .Select(this.runnerFactory.Create) 
      .Select(runner => Task.Run((Action) runner.Run)) 
      .ToArray(); 

     Task.WaitAll(runners); 
    } 
} 


// you could also use .InNamedScope() or maybe InParentScope() or InCallScope() -- see the NamedScope extension! 
kernel.Bind<IControl>().To<Control>().InSingletonScope(); 

// implementation is auto generated. 
kernel.Bind<IRunnerFactory>().ToFactory(); 

kernel.Bind<IConfig>().To<Config1>(); 
kernel.Bind<IConfig>().To<Config2>(); 
kernel.Bind<IConfig>().To<Config3>(); 

참고 :


솔루션은 2

우리는 해결 방법 1에 확장하고 우리가 IReadOnlyCollection<Runner>를 삽입 할 수 바인딩 제공/.ToProvider()를 사용하는 것입니다. 명시 적으로 IReadOnlyCollection<Runner> 바인딩 및 Ninject에의 사용하고 있지 있기 때문에,하지만 IEnumerable<Runner> 또는 다른 종류의 멀티 - 바인딩 -

public class RunnersProvider : Provider<IReadOnlyCollection<Runner>> 
{ 
    private readonly IList<IConfig> runnerConfigurations; 
    private readonly IRunnerFactory runnerFactory; 

    public RunnersProvider(IList<IConfig> runnerConfigurations, IRunnerFactory runnerFactory) 
    { 
     this.runnerConfigurations = runnerConfigurations; 
     this.runnerFactory = runnerFactory; 
    } 

    protected override IReadOnlyCollection<Runner> CreateInstance(IContext context) 
    { 
     return this.runnerConfigurations 
      .Select(this.runnerFactory.Create) 
      .ToArray(); 
    } 
} 


kernel.Bind<IReadOnlyCollection<Runner>>().ToProvider<RunnersProvider>(); 

당신은 다음

IResolutionRoot.Get<IReadOnlyCollection<Runner>>() 

또는도의 ctor에 IReadOnlyCollection<Runner>를 주입 할 수 있습니다/다중 분사 기능. 취성 -

은 또한 당신은 kernel.Bind<IEnumerable<Foo>>() (자동 다중 분사에 대한 지원 Ninject에 모든 유형의 동일 IList<>, ICollection<>foo[] 적용) 점에 유의해야합니다.kernel.Get<IEnumerable<Foo>>()을 사용할 수 있지만 ctor-inject에 사용하는 경우 ninject는 (다중 분사 지원)이 아닌 Foo에 일치하는 바인딩을 찾으려고하기 때문에 동일한 유형을 ctor-inject 할 수 없습니다.

+0

유망 해 보입니다. 조금^_^ 과 관련하여 IConfig 개체가 App.config의 foreach 변환 문자열을 사용하여 추가됩니다. foreach (Config.select (JSON )의 IConfig c) 바인딩 () .ToConstant (c); 더 좋은 방법이 있습니까? 위의 Config 속성은 Properties.Settings.Default에 대한 래퍼 일뿐입니다 ... –

+0

IConfig 바인딩을 전혀 고려하지 않아야합니다. 대신'IConfigReader'를'IEnumerable ReadConfig()'메소드로 바인딩하십시오. – BatteryBackupUnit

+0

IConfigReader 접근법과 함께 솔루션 1을 시도한 후 configs.Select (factory.Create) .ToList()를 호출 할 때 IConfig를 활성화하는 중 오류가 발생합니다. –