Using MediatR from within a message handler (Rebus). The message handler is where the context lives and dies once the message is handled. Thinking the following:
public class MessageHandler: IHandleMessages<Thing> {
public MessageHandler(
IContainer container
// other dependencies
) {
Container = container;
...
}
protected IContainer Container { get; }
public async Task Handle(Thing message)
{
using(var scope = Container.BeginLifetimeScope())
{
var mediator = scope.Resolve<IMediator>();
mediator.Send(new SuperCommand { .... super paramters });
}
}
}
Question is if passing around the IContainer is an anti-pattern? MediatR with AutoFac usually is configured to resolve the query | command handlers via IComponentContext
so that when the IMediator is disposed the handlers are disposed.
Question is if passing around the IContainer is an anti-pattern?
It depends on its use. The book Dependency Injection Principles, Practices, and Patterns describes (in §5.2) that supplying application components outside the Composition Root with access to an unbounded set of Volatile Dependencies is an anti-pattern called Service Locator.
In your case, the IContainer
interface allows access to an unbounded set of dependencies. This is because its Resolve<T>
method allows you to resolve any type. This makes the IContainer
interface a candidate for becoming a Service Locator. Whether or not it is used as Service Locator, however, depends on how it's used.
The book very precisely defines a Service Locator as a pattern applied "outside the Composition Root" as referencing the container, or any such abstraction, within the Composition Root does not cause the same downsides.
In other words, you are free to inject IContainer
into your class, e.g. MessageHandler
, as long as that implementation is defined inside the application's Composition Root. That would make MessageHandler
an infrastructural component.