Reputation: 71
Is it possible to use IServiceProvider
inside IServiceCollection.Configure()
?
I see no overload on Configure()
to accept something like Func<IServiceProvider, T
>. Other extension methods, like IServiceCollection.AddScoped()
have an overload which accepts Func<IServiceProvider, T>
.
I would like to do something like this:
public static void AddCommandHandlers(this IServiceCollection services, Assembly assembly)
{
// CommandExecutor has a dependency on CommandHandlerFactory
services.AddScoped<CommandExecutor>();
services.Configure<CommandHandlerFactory>(myFactory =>
{
// How can I use IServiceProvider here? Example scenario:
foreach(Type t in FindHandlers(assembly))
myFactory.AddHandler(serviceProvider => serviceProvider.GetService(t));
});
}
The goal is to be able to call AddCommandHandlers
extension method multiple times, for different assemblies, and append found handlers (using DI) to the same CommandHandlerFactory
, so that CommandExecutor
can just call the factory to obtain a handler.
Or maybe there is another way?
Any help appreciated.
Thanks.
Upvotes: 5
Views: 4366
Reputation: 14419
You could register each command handler against a common interface:
foreach(Type t in FindHandlers(assembly))
services.AddScoped<ICommandHandler>(t);
Then you could make the factory accept IEnumerable<ICommandHandler>
as a constructor parameter.
public class CommandHandlerFactory
{
public CommandHandlerFactory(IEnumerable<ICommandHandler> handlers)
{
foreach(var handler in handlers)
AddHandler(handler);
}
// The rest of the factory
}
Or, if you can't change the constructor, you could setup the factory like this:
services.AddSingleton(serviceProvider =>
{
var factory = new CommandHandlerFactory();
foreach(var handler in serviceProvider.GetServices<ICommandHandler>();
factory.AddHandler(handler);
return factory;
});
Upvotes: 1
Reputation: 143
You can call the BuildServiceProvider() extension method on the IServiceCollection at any time to build a ServiceProvider. You'll need Microsoft.Extensions.DependencyInjection
It will obviously only include any services which have already been added to the collection so you'll need to call things in the correct order.
IServiceProvider sp = services.BuildServiceProvider();
Upvotes: 2