I’m currently helping a client implement a multi-tenant service based on NServiceBus. First things first: yes, I’m aware of the article Injecting tenant-aware components into message handlers, and I’ve read it, downloaded the sample code, and contemplated my options. I hope something simpler would be possible.
My client has quite a few message handlers like this one:
public class CreateCustomerHandler : IHandleMessages<CreateCustomer>
{
public CreateCustomerHandler(HttpClient client)
{
Client = client;
}
public HttpClient Client { get; }
public async Task Handle(
CreateCustomer message,
IMessageHandlerContext context)
{
// Use Client here to communicate with a REST API...
}
}
The client
dependency should come equipped with tenant-specific credentials (and possibly other configuration). Thus, we’ll have to find a way to create an HttpClient
object per tenant, or possibly per message.
The problem isn’t one of lifetime configuration; I know about DependencyLifecycle.InstancePerUnitOfWork
.
The problem is how to pick or create an HttpClient
object for a given tenant. We’ll have some configuration data that’ll enable us create and configure an HttpClient
object based on a tenant ID, but how do we configure NServiceBus so that a message handler receives an HttpClient
dependency for the tenant that relates to the message
?
I’m aware that we could inject some hypothetical IHttpClientFactory
or IDictionary<int, HttpClient>
as a dependency instead of just an HttpClient
dependency, but I’d prefer not doing that, since it just makes everything (including unit testing) more complicated than it has to - not to mention that it’d violate the Dependency Inversion Principle.
Does NServiceBus have an extensibility point we can override to create instances of dependencies for a given message?
I’m aware of the four overloads of IConfigureComponents.ConfigureComponent
, but I can’t see any obvious way to react to any tenant ID in that API. Perhaps I’m missing something?