Search code examples
c#design-patternsasp.net-coreclass-design

Why is ASP.NET Core's Startup class not an interface or abstract class?


This is in regards to the design principals behind the Startup class explained here:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.1

I understand that the class needs to include methods like ConfigureServices or Configure.

Why CreateDefaultBuilder(args).UseStartup<Startup>() does not mandate any base class or interface for better readability?

With this design approach, someone must read the documentation and know about the magic method names like ConfigureServices or Configure.

If this is part of a new class design mindset, then where can I read more about it?


Solution

  • There are several reasons why its done the way its done. One of the more obvious reasons is, because you can inject services into Configure method, such as

    public void Configure(IAppBuilder app, IMyService myService)
    {
        myService.DoSomething();
    }
    

    Obviously, you can't do that with interfaces, abstract classes or inheritence.

    The second reason why its done by convention method is, that there is not only Configure/ConfigureServices method, there is an infinite number of environment-dependent configure methods.

    public void Configure(IAppBuilder app) { }
    public void ConfigureDevelopment(IAppBuilder app) { }
    public void ConfigureProduction(IAppBuilder app) { }
    public void ConfigureStaging(IAppBuilder app) { }
    public void ConfigureSomethingElse(IAppBuilder app) { }
    

    and depending on your environment variable for ASPNET_ENVIRONMENT a different method will be chosen and executed (or the default Configure/ConfigureServices if no matching environment specific method was found).

    None of this is possible with traditional OOP (inheritance/interfaces/abstract classes).

    The same applies to other parts of ASP.NET Core, like Middlewares and the Invoke Method. The Invoke method can also have dependencies injected into it, but in order to call the next middleware you simply do

    await next?.Invoke();
    

    and do not have to worry which dependencies the next middleware requires or may take.

    And to be complete, one can also have multiple Startup classes with the default method names (Configure/ConfigureServices) named StartupDevelopment, StartupProduction, Startup (as fallback) and ASP.NET Core will pick up the correct one based on Environment variable set.