public static IServiceCollection AddHardware(this IServiceCollection serviceCollection) { return(serviceCollection .AddCompositeDispenser((sp) => { KioskSettings kioskSettings = sp.GetRequiredService <KioskSettings>(); if (kioskSettings.Dispenser.Mode == OptionUseCase.Off) { return null; } return new CompositeDispenserBuilder() .AddStrategy(sp.GetRequiredService <IDispensingStrategy>()) .AddDispensers(() => kioskSettings.Dispenser.SlaveMachines.Select(x => { if (x.Model.Equals("VisionEsPlus", StringComparison.InvariantCultureIgnoreCase)) { VisionEsPlusSettings settings = new VisionEsPlusSettings { PortNumber = (ushort)x.Port, Address = x.Address, IpAddress = x.IpAddress }; ICommunicationChannel channel = null; if (kioskSettings.Dispenser.Mode != OptionUseCase.Off) { switch (x.Protocol) { case Utils.Common.Enum.CommunicationProtocol.Serial: channel = new SerialPortChannel(settings.PortNumber, settings.BaudRate, settings.Timeout, settings.CommandsSendDelay); break; case Utils.Common.Enum.CommunicationProtocol.TCP: channel = new TcpChannel(settings.IpAddress, settings.PortNumber); break; default: break; } } return new VisionEsPlusVendingMachine(x.Number.ToString(), new VisionEsPlus(channel, settings)); } else { throw new ArgumentException("Unknown dispenser model"); } }) ).Build(); }) .AddLayout((sp) => { KioskSettings kioskSettings = sp.GetRequiredService <KioskSettings>(); if (kioskSettings.Dispenser.Mode == OptionUseCase.Off) { return null; } ILayoutBuilder layoutBuilder = new LayoutBuilder(); if (kioskSettings.Dispenser.SlaveMachines.Any(x => !x.Number.HasValue || x.Number == 0)) { throw new ArgumentException("Machine number is mandatory"); } kioskSettings.Dispenser.SlaveMachines.ToList().ForEach(x => { if (x.Model.Equals("VisionEsPlus", StringComparison.InvariantCultureIgnoreCase)) { // TODO: Refactor this stub if (x.Number == 1) { layoutBuilder.AddMachine <VisionEspMachine, VisionEspTray, VisionEspBelt>(x.Number.Value) .AddTray(11) .AddBelt(2).CommitTray() .AddTray(18) .AddBelt(0).AddBelt(1).AddBelt(2).AddBelt(3).AddBelt(4).AddBelt(5).CommitTray().CommitMachine(); } if (x.Number == 2) { layoutBuilder.AddMachine <VisionEspMachine, VisionEspTray, VisionEspBelt>(x.Number.Value) .AddTray(11) .AddBelt(0).AddBelt(1).AddBelt(2).AddBelt(3).AddBelt(4).CommitTray().CommitMachine(); } } else { throw new ArgumentException("Unknown dispenser model"); } }); return layoutBuilder.Build(); }) .AddCashPayment((sp, cs) => { KioskSettings kioskSettings = sp.GetRequiredService <KioskSettings>(); IEnumerable <ICashDeviceAdapter> cashDevices = null; switch (kioskSettings.Cashbox.Mode) { case OptionUseCase.Emulation: cashDevices = new ICashDeviceAdapter[] { new MockBillAcceptor(sp.GetRequiredService <ICurrencyConverter>(), (s) => { s.IssueIndex = 1; s.BaseCurrency = kioskSettings.BaseCurrency; // Stub s.BillsToReceive = new Money[] { Money.Create(100, CurrencyCode.USDollar), Money.Create(500, CurrencyCode.RussianRouble) }; // Stub s.BillsToGiveChange = new Money[] { Money.Create(50, CurrencyCode.RussianRouble), Money.Create(1, CurrencyCode.USDollar) }; // Stub }) }; break; case OptionUseCase.Off: cashDevices = null; break; case OptionUseCase.On: // ... break; } cs.CashDevices = cashDevices; return cs; }) .AddEcommerce((sp, es) => { KioskSettings kioskSettings = sp.GetRequiredService <KioskSettings>(); foreach (var provider in kioskSettings.ECommerceSettings.PaymentProviders) { switch (provider.Source) { case PaymentSource.UVS: if (kioskSettings.ECommerceSettings.Mode == OptionUseCase.Emulation) { es.Add(new UvsMockEcommerceService(sp.GetRequiredService <ICurrencyConverter>(), (settings) => { settings.BaseCurrency = kioskSettings.BaseCurrency; })); } else if (kioskSettings.ECommerceSettings.Mode == OptionUseCase.On) { // ... } break; default: throw new ArgumentException("Invalid ecommerce source"); } } return es; }) .AddEventMediation((sp, broker) => { broker.AppendProducer(sp.GetRequiredService <IPaymentProvider>() as IEventProducer); broker.AppendProducer(sp.GetRequiredService <ICashPaymentService>() as IEventProducer); broker.AppendProducer(sp.GetRequiredService <ICompositeDispenser>() as IEventProducer); broker.AppendProducer(sp.GetRequiredService <IStorageService>() as IEventProducer); broker.AppendProducer(sp.GetRequiredService <IAttendant>() as IEventProducer); broker.AppendProducer(sp.GetRequiredService <ISlipService>() as IEventProducer); }) .AddSingleton((sp) => new EventConsumer() .AppendWriter <IPaymentProvider>(new EventWriter <IPaymentProvider>(sp.GetRequiredService <ILogger <IPaymentProvider> >())) .AppendWriter <ICashPaymentService>(new EventWriter <ICashPaymentService>(sp.GetRequiredService <ILogger <ICashPaymentService> >())) .AppendWriter <ICompositeDispenser>(new EventWriter <ICompositeDispenser>(sp.GetRequiredService <ILogger <ICompositeDispenser> >())) .AppendWriter <IStorageService>(new EventWriter <IStorageService>(sp.GetRequiredService <ILogger <IStorageService> >())) .AppendWriter <IAttendant>(new EventWriter <IAttendant>(sp.GetRequiredService <ILogger <IAttendant> >())) .AppendWriter <ISlipService>(new EventWriter <ISlipService>(sp.GetRequiredService <ILogger <ISlipService> >())))); }