假设我们有以下实现:
public class SerialPortAddress
{
public SerialPortAddress(string address)
{
this.Address = address;
}
public string Address { get; }
}
public interface ISerialPort
{
SerialPortAddress Address { get; }
}
public class SerialPort : ISerialPort
{
public SerialPort(SerialPortAddress address)
{
this.Address = address;
}
public SerialPortAddress Address { get; }
}
public interface IDeviceDriver
{
ISerialPort SerialPort { get; }
}
public class DeviceDriver : IDeviceDriver
{
public DeviceDriver(ISerialPort serialPort)
{
SerialPort = serialPort;
}
public ISerialPort SerialPort { get; }
}
多重注入
然后我们可以如下创建绑定并检索IDeviceDrivers 及其串行端口列表,如下所示:
public class Test
{
[Fact]
public void Bla()
{
var com1 = new SerialPortAddress("COM1");
var com2 = new SerialPortAddress("COM2");
var kernel = new StandardKernel();
kernel.Bind<ISerialPort>().To<SerialPort>();
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com1, true));
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com2, true));
var deviceDrivers = kernel.Get<List<IDeviceDriver>>();
deviceDrivers.Should().HaveCount(2)
.And.Contain(x => x.SerialPort.Address == com1)
.And.Contain(x => x.SerialPort.Address == com2);
}
}
另见Multi Injection
命名绑定
或者,如果您需要知道哪个IDeviceDrivers 是哪个,您也可以使用命名绑定:
[Fact]
public void NamedBindings()
{
const string DeviceDriver1 = "DeviceDriver1";
const string DeviceDriver2 = "DeviceDriver2";
var com1 = new SerialPortAddress("COM1");
var com2 = new SerialPortAddress("COM2");
var kernel = new StandardKernel();
kernel.Bind<ISerialPort>().To<SerialPort>();
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.Named(DeviceDriver1)
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com1, true));
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.Named(DeviceDriver2)
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com2, true));
kernel.Get<IDeviceDriver>(DeviceDriver1).SerialPort.Address.Should().Be(com1);
kernel.Get<IDeviceDriver>(DeviceDriver2).SerialPort.Address.Should().Be(com2);
}
工厂
最后,你也可以通过工厂创建组件,这需要一个工厂接口开始:
public interface IDeviceDriverFactory
{
IDeviceDriver Create(SerialPortAddress address);
}
使用Ninject.Extensions.Factory,我们现在可以执行以下操作:
[Fact]
public void Factory()
{
var com1 = new SerialPortAddress("COM1");
var com2 = new SerialPortAddress("COM2");
var kernel = new StandardKernel();
kernel.Bind<ISerialPort>().To<SerialPort>();
kernel.Bind<IDeviceDriver>().To<DeviceDriver>();
kernel.Bind<IDeviceDriverFactory>()
.ToFactory(() => new TypeMatchingArgumentInheritanceInstanceProvider());
var factory = kernel.Get<IDeviceDriverFactory>();
factory.Create(com1).SerialPort.Address.Should().Be(com1);
factory.Create(com2).SerialPort.Address.Should().Be(com2);
}
编辑:Ninject.Extension.Factory 可能无法在树莓派上运行。
如果是这种情况,您可能需要自己实现工厂:
public class DeviceDriverFactory : IDeviceDriverFactory
{
private readonly IResolutionRoot resolutionRoot;
public DeviceDriverFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IDeviceDriver Create(SerialPortAddress address)
{
var serialPortAddressParameter = new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, t) => address)
this.resolutionRoot.Get<IDeviceDriver>(serialPortAddressParameter);
}
}
Bind<IDeviceDriverFactory>().To<DeviceDriverFactory>();