Using DI in ConfigureService-Methods (especially I

2019-07-14 02:49发布

问题:

I'm trying to implement a new extension method for the IWebHostBuilder that executes some code, like registering somewhere. The important part is, that it also unregisters when the application is shutting down.

I added some code which shows what I want to do. The problem here is, that the instance of IApplicationLifetime is not available yet. This new extension method was added last in the pipeline of building the WebHost.

public static IWebHostBuilder UseHttpGatewayappRegistration(this IWebHostBuilder webHostBuilder)
    {
        webHostBuilder.ConfigureServices(services =>
        {
            var sp = services.BuildServiceProvider();

            // This instance is not available
            IApplicationLifetime applicationLifetime = sp.GetService<IApplicationLifetime>();

            // These instances are ok
            AppSettings appSettings = sp.GetService<AppSettings>();
            ILoggerFactory loggerFactory = sp.GetService<ILoggerFactory>();

            var registration = new Registration(loggerFactory.CreateLogger<Registration>());

            applicationLifetime.ApplicationStopping.Register(() =>
            {
                registration.Unregister();
            });
        });

        return webHostBuilder;
    }

Why is the IApplicationLifetime instance null, even though I added this extension method last in the pipeline of building the WebHost pipeline? It would be great, if someone would provide me with some information about the execution order of all "ConfigureServices" methods and how or if it is at all possible to use IApplicationLifetime in a ConfigureServices method.

I know I could do this all without the WebHostBuilder, but it seems logical to me to do it there and I also think there has to be a way.

Unfortunately I couldn't find much information online...

Thank you.

EDIT: I found a way to use DI in ConfigureServices methods. I edited the question accordingly. This helped me: How to Resolve Instance Inside ConfigureServices in ASP.NET Core

回答1:

You can't get access to IApplicationLifetime instance from ConfigureServices method. It's by design. Check the "Services Available in Startup" section here: Application Startup in ASP.NET Core.

Resolve IApplicationLifetime in the IWebHostBuilder.Configure method (it replaces the Startup.Configure method if it is used later in IWebHostBuilder configuration pipeline):

public static IWebHostBuilder Foo(this IWebHostBuilder webHostBuilder)
{
    webHostBuilder.Configure(x =>
    {
        var service = x.ApplicationServices.GetService<IApplicationLifetime>();
    });

    return webHostBuilder;
}

It's also possible to extend the original Startup.Configure method instead of replace (a lot of Reflection logic should be added to make this solution reliable):

.Configure(app =>
{
    var env = app.ApplicationServices.GetService<IHostingEnvironment>();
    dynamic startup = Activator.CreateInstance(typeof(TStartup), env);

    //Carefully resolve all input parameters.
    //Make sure all required services are registered in DI.
    startup.Configure(app, env);

    var lifetime = app.ApplicationServices.GetService<IApplicationLifetime>();
})