Darek
Darek

Reputation: 71

How to use IServiceProvider inside IServiceCollection.Configure()

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

Answers (2)

Connell
Connell

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

Nick
Nick

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

Related Questions