0

Having net5.0 app, I would like to utilize UseNServiceBus(...) extension provided by NServiceBus.Extensions.Hosting to build the endpoint, wrap it to an IHostedService and run/stop it on app start/stop.

Unfortunately I would need to access other classes from container to fully create the EndpointConfiguration. This is not possible, because there is no container (IServiceCollection) nor the provider (IServiceProvider).

Is there any trick, I could resolve services in the lambda passed to UseNServiceBus?

Something like:

hostBuilder
    .ConfigureServices((hostContext, services) =>
    {
        services
            .AddSingleton<CoolEndpointConfigBuilder>()
            .AddSingleton<SomeDependency>(sp => 
            {
                /* 
                 * We can access sp in this context to resolve anything
                 * helpful in the process of SomeDependency's creation
                 */ 
            })
            .AddOtherDependencies()
        ;
    })
    .UseNServiceBus(hostContext => 
    {
        // How to get it here?
        IServiceProvider sp = PerformSomeVooDooToGetServiceProvider();

        var cecb = sp.GetRequiredService<CoolEndpointConfigBuilder>();

        /*
         * Which assembles EndpointConfiguration using the myriad of classes 
         * injected to the CoolEndpointConfigBuilder's constructor
         */
        return cecb.Build();
    });
sharpener
  • 1,383
  • 11
  • 22

1 Answers1

1

There is no IServiceProvider available yet when UseNServiceBus is called. UseNServiceBus is internally also just using IHostBuilder.ConfigureServices so it is limited to the same constraints. You are trying to resolve services from the container while the host hasn't created the IServiceProvider. NServiceBus also requires the DI container managed by the host, so there is no way of already resolving dependencies while NServiceBus is still being configured. In essence, you should be able to configure your endpoint without needing dependency injection. Why does your configuration require DI?

If you really want to hack around this (I'd strongly advise against it), you can create a temporary DI container at configuration time for the types you need, e.g. something like

hostBuilder
    .UseNServiceBus(hostContext => 
    {
        var tempServiceCollection = new ServiceCollection();
        tempServiceCollection.AddSingleton<CoolEndpointConfigBuilder>();

        var tempServiceProvider = tempServiceCollection.BuildServiceProvider();

        var cecb = tempServiceProvider.GetRequiredService<CoolEndpointConfigBuilder>();

        return cecb.Build();
    });

This is of course very limited but depending on your DI needs might help.

Sabacc
  • 789
  • 6
  • 13
  • 2
    To add what @sabacc said: MS clearly states you should avoid using `BuildServiceProvider` in their recommendations https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines#recommendations – Daniel Marbach Mar 16 '21 at 18:53
  • 1
    Yes, just like this comment. You should not want to `IServiceProvider` in the configuration of NServiceBus. They only thing you need there is `IConfiguration` and `IHostEnvironment`. Your handlers and saga's share DI with the standard dotnet core. – Benj Mar 18 '21 at 08:53