Is it possible to add a service to an IServiceProvider
when creating a new scope?
E.g. a scope is created like this:
using (var scope = Services.CreateScope())
{
// Register some service using "AddScoped"
scope.??.AddScoped<IOrganizationIdProvider, OrganizationIdProvider>((x) => { return new OrganizationIdProvider("dynamic-parameter")});
// Resolve service
scope.ServiceProvider.GetService<IOrganizationIdProvider>();
}
The service should be resolved when creating new instances in the scope.
@Nkosi already mentioned that you can't make new registrations in MS.DI once the container has been created. But even if you could, changing the container in-flight is a bad idea, which is why most DI Container do not support such feature. The newest versions of Autofac and Ninject, for instance, recently removed such feature, and the Simple Injector documentation explains why it never had this feature.
But you can achieve what you want by making small changes to your code. Probably the easiest way to implement this is by making changing injecting the dynamic parameter through property injection instead of constructor injection. For instance:
Changes in application code:
public class OrganizationIdProvider : IOrganizationIdProvider
{
// Only required code change (notice that the interface doesn't change, this
// property is an implementation detail)
public string DynamicParameter { get; set; }
}
Configuration of the container:
// Register the implementation by itself to allow it to be requested by your infrastructure
services.AddScoped<OrganizationIdProvider>();
// Register the provider by its interface so it can be injected into application components
services.AddScoped<IOrganizationIdProvider>(c => c.GetService<OrganizationIdProvider>());
Usage:
using (var scope = Services.CreateScope())
{
// Here we resolve the OrganizationIdProvider *implementation*
var provider = scope.ServiceProvider.GetRequiredService<OrganizationIdProvider>();
// Set the runtime parameter
provider.DynamicParameter = "dynamic-parameter";
// Resolve service that might have a dependency on IOrganizationIdProvider.
var handler =
scope.ServiceProvider.GetRequiredService(typeof(IMessageHandler<DoSomething>));
// Use the service
handler.Handle(new DoSomething());
}
There are certainly more options when it comes to dealing with runtime data, but for that I would recommend you to read this series on DI Composition Models.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With