I'm trying to use Ninject as my IoC framework for a Windows Service. I have the following classes and interfaces:
Assembly Core:
public class Orchestrator : IOrchestrator
{
...
public Orchestrator(ITerminal terminal)
{
...
}
...
}
Assembly Vx520:
public class Vx520 : ITerminal
{
...
public Vx520(string comPort, int bauds, int dataBits, Parity parity, StopBits stopBits)
{
...
}
...
}
Assembly Vx580:
public class Vx580 : ITerminal
{
...
public Vx580(string ip, int port)
{
...
}
...
}
My idea is to use a ConfigurationSection
to let the user configure which and how many terminals he wants. For example, in the following configuration, I should get 3 Orcestrator instances, one with a Vx520 terminal, and the other two with Vx580, each with it's custom configuration:
<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>
I have the configuration part working, with an IEnumerable<TerminalConfiguration>
as the final output.
Is there a way to dynamically resolve the dependency for the Orchestrator
class using this list of configurations?
If Ninject is uncapable of doing this, is there other IoC framework that you can recommend me?
Thank you in advance
Ninject (or most or even all DI containers for that matter) cannot be used to control how many objects to instantiate based on some arbitrary "external" information. What you can do is having multiple bindings, like so:
and then inject them (ctor argument of type
IEnumerable<IOrchestrator>
or retrieve them byIResolutionRoot.GetAll<IOrchestrator>()
. That will result in exactly 3 instances. You can also have conditional (contextual) bindings where you put a condition on a binding, for example:and when you inject
ITerminal
/ doIResolutionRoot.Get<ITerminal>()
you will get aVx520
orVx580
(or a missing binding exception!) depending on the value ofConfig.Terminal.Type
.Now, of course, you could parse the config and create the bindings accordingly:
So you would have 3 bindings for
IOrchestrator
, each with aConstructorArgument
which holds it's config. Since theConstructorArgument
hasshouldInherit
set to true, the types down theIOrchestrator
tree can it injected and can also have conditions injected to it. For example, you could do something along the lines of:and also have the
ITerminalConfig
injected intoVx520
(that's how you would get the IP & Port / comport & baudrate,.. settings).But to be honest, instead of creating multiple
Bind<IOrchestrator>().To<Orchestrator>()
bindings, wouldn't it be better to have the creation done explicitly? Per some service initializer / application startup step which uses anIOrchestratorFactory
to create the instances?