How to configure DI services available to the Startup class constructor

asp.net-core, c#, dependency-injection

Solution

Although Steven's concerns are valid and you should take note of them, it is technically possible to configure the DI container that is used to resolve your Startup class.

ASP.NET hosting uses dependency injection to wire up an instance of your Startup class and also let us add our own services to that container using the `ConfigureServices` extension method on `IWebHostBuilder`:

var host = new WebHostBuilder()
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .ConfigureServices(services => services.AddSingleton<IMyService, MyService>())
    .UseStartup<Startup>()
    .Build();

host.Run();

and:

public Startup(IMyService myService)
{
    myService.Test();
}

In fact, all that `UseStartup<WebStartup>` does is adding it as a service implementation of `IStartup` to the hosting DI container (see this).

Please note that instances of your services will be resolved again in the application container as a new instance of the `IServiceProvider` will be built. The registration of the services will, however, be passed to the application `IServiceCollection` in your Startup class.

Problem

When I create the webhost for an ASP.NET Core application I can specify the `Startup` class but not an instance. The constructor of your own Startup class can take parameter which are provided through DI. I know how to register services for DI within `ConfigureServices` but as that is a member of that class these services are not available for the constructor of my startup class. How do I register services which will be available as constructor parameter of the Startup class? The reason is that I have to supply an object instance which must be created outside/before the webhost is created and I do not want to pass it in a global-like style. Code to create the IWebHost: ``` this.host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseIISIntegration() .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup<WebStartup>() log.Debug("Run webhost"); this.host.Start(); ``` Constructor of `WebStartup`: ``` public WebStartup(IHostingEnvironment env, MyClass myClass) { var config = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddEnvironmentVariables() .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) .Build(); ... } ``` So specifically, how to I register `MyClass` in this example (which obviously must be done before `WebStartup` is instanciated by the `IWebHost`)?

Original source