user2727195
user2727195

Reputation: 7340

Getting reference of Startup.cs object

Here's the skeleton of a standard ASP.NET Core application:

var config = new ConfigurationBuilder()
    .AddCommandLine(args)
    .AddEnvironmentVariables(prefix: "ASPNETCORE_")
    .Build();

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup<Startup>()
    .Build();

host.Run();

In this piece the ASP.NET Core apparatus instantiates an instance of Startup.cs class

.UseStartup<Startup>()

My query is how can I get hold (reference) of this already instantiated instance of Startup object that I can plug into my Library/Framework.

Context is to setup some Uber level framework and get a reference of this junction (Startup.cs) where all the requests are getting initiated.

Upvotes: 7

Views: 3519

Answers (1)

Evk
Evk

Reputation: 101593

If your Startup implements IStartup interface, getting reference to it is easy:

var host = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

var startup = host.Services.GetService(typeof(IStartup)); // or from any other part of code using IServiceProvider.

However, asp.net core does not require your startup class to implement this interface. If it does not - it will use adapter pattern and adapt your Startup class to IStartup interface. You will still have an instance of IStartup, but it will not be your Startup class. Instead it will be an instance of ConventionBasedStartup. Asp.net core will explore methods of your startup class, find Configure and ConfigureServices methods and will pass them to ConventionBasedStartup which will adapt them to IStartup interface. In this case, it's not possible to retrieve instance of your startup class without heavy reflection, because it's not actually stored in any field (even in private) of ConventionBasedStartup and is only reachable through delegate references.

Long story short - if you want to get instance of your Startup class - make it implement IStartup interface.

Update about how to implement IStartup interface:

public class Startup : IStartup
{
    public Startup(IHostingEnvironment env)
    {
        // constructor as usual
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void Configure(IApplicationBuilder app) {            
        app.UseMvc();
        // resolve services from container
        var env = (IHostingEnvironment) app.ApplicationServices.GetService(typeof(IHostingEnvironment));
        var logger = (ILoggerFactory)app.ApplicationServices.GetService(typeof(ILoggerFactory));
        logger.AddConsole(Configuration.GetSection("Logging"));
        logger.AddDebug();
        // etc
    }        

    public IServiceProvider ConfigureServices(IServiceCollection services) {
        services.AddMvc();
        // etc
        // return provider
        return services.BuildServiceProvider();
    }
}

Upvotes: 11

Related Questions