I have a Mediator application using Simple Injector for command handler registration, and injection and handlers is all setup and working perfectly.
class DoWashingCommandHandler : IRequestHandler<DoWashingCommand,object>
{
IBus bus;
public DoWashingCommandHandler(IBus bus) { this.bus = bus; }
Task<object> Handle(DoWashingCommand command)
{
this.bus.Send(new OtheCommand());
}
}
I have a need for 2 registrations of a IBus implementations.
The first can be of any lifetime, the second has a background thread so i initially thought it would need to be a singleton but on review i believe it could also be of any lifetime and just have a static worker thread class within it (this would be important for scope):
// register as non-singleton to allow scope usage
// keep static worker thread as if it were Singleton
class DispatchOnBackgroundThread : IBus
{
static Worker = new Worker();
public Task<object> Send(object command)
{
Worker.Post(command);
}
public void Start(Container container, CancelationToken stoppingToken)
{
Worker.Start(container,stoppingToken);
}
class Worker
{
public void Post(object command) { /* snip */ }
public void Start(Container container, CancelationToken stoppingToken)
{ /* snip */ }
public void Thread()
{
/* loop */
var item = ReadFromQueue();
// get command handler type
// get command handler instance from container
// if instantiated instance has IBus dependency in this
// section then it must have used DispatchInThread as the
// concrete implementation for IBus (including if the handler
// calls container.GetInstance<IBus>()
handler.Handle(item.Request, cancellationToken);
}
// anything outside this Thread should use
// DispatchOnBackgroundThread for IBus
}
}
Then the registrations would be as follows (not sure how to avoid the double registration issue of IBus):
// i need to be able to register two types
container.Register<IBus,DispatchOnBackgroundThread>();
container.Register<IBus,DispatchInThread>();
// this would return any IBus references with DispatchOnBackgroundThread
var handler = this.container.GetInstance(requestHandlerType);
using(SomeSope.BeingScope(container))
{
// this would return any IBus references with DispatchInThread
var handler = this.container.GetInstance(requestHandlerType);
// and if handler or other code referenced container and called
// GetInstance, and IBus dependencies would be returned as
// DispatchInThread whilst in this scope
}
// this would return any IBus references with DispatchOnBackgroundThread
var other = this.container.GetInstance(requestHandlerType);
I think and in summary, this is a mix of Context-based injection and custom scope.
How can I achieve the above or is this a terrible code smell?
To give further context if required I need the above switchable resolved types in order to implement the solution of another question https://stackoverflow.com/a/61782405/915839
DI code is removed in above link, but i am very much using SimpleInjector in the actual implementation
DispatchInThreadas a decorator ofDispatchOnBackgroundThread? - qujckDispatchRouter : IBusthat references both dispatcher implementations and makes the decision as to which one to call. Lots of options. - qujck