If you're an Asp Net core guy, you should be familiar with the nightmare that is startup file organization. Every Asp core application startup file can includes configurations, middleware declaration, dependency injection definition, authentication configs, policies amonst other things. So long story short : heavy applications have large messy unreadable startup files with hundreds of lines of, hard to scroll through, code.
Meet extension methods, your new bestfriends
So, as you might have guessed, here is where extension methods come to the rescue. Learning to organize your Startup.cs is part of being a good C# programmer and having extension methods in your arsenal is a must. By the end of this article, you will learn a neat and simple trick to improve the organization of your startup files and spare yourself the pain of endless startup file scrolling in your future projects.
"Extension Method" was introduced with C# 3.0, and since then, the sun has been shining a little brighter.
Extension methods can be used to extend an existing type without creating a derived type, recompiling or modifying the original one.
As a brief example, let's say we want to add a special method CountChar
to the class String using the Extension Method. CountChar
will simply count the number of occurences of a specific character in a given string.
namespace ExtensionMethods
{
public static class MyExtensions
{
public static int CountChar(this String str,Char character)
{
return str.Count(x=> x == character);
}
}
}
Now to use it, we just need to import the name space ExtensionMethods
in our project, and voilà ! Thanks to the magic of IntelliSense, our new method CountChar
is now usable for any object of type String.
Check out Microsoft docs page for more examples here.
Unleash the full potential of extension methods
Now let's do something more complex : we will extend the IServiceCollection
and the IApplicationBuilder
.
To do that we need to:
- Create a static class:
This class will include all our extension methods
- Create our extension method passing our type as parameter with the keyword this.
In our example we will take Swagger configuration as an example:
namespace ExtensionMethods
{
public static class SwaggerConfigurationExtension
{
public static void AddSwaggerConfig(this IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
}
public static void UseCustomSwaggerConfig(this IApplicationBuilder app)
{
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
}
}
}
In the code above, we created two extension methods:
AddSwaggerConfig
extends theIServiceCollection
to add the swagger generator configuration.UseCustomSwaggerConfig
extends theIApplicationBuilder
to enable middleware for swagger server generation and swagger UI.
The calls in the startup file will be done as follows:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerConfig()
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCustomSwaggerConfig()
}
}
In terms of startup extension organization, two possibilities present themselves :
Regoup all your extensions in a single class (called StartupExtension for example).
Create a class for each feature or service added to the IServiceCollection.
Personnaly, I prefer the second solution. Usually I create a folder named Extensions and I put all my classes there. With this structure I can re-use an extension in an other projet with coping just the file that I need rather then coping code.
So with those methods we will have a startup file that looks like this :
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerConfig()
services.AddCustomAuthentification()
services.AddCustomSettingsFile()
services.AddHttpClients()
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCustomSwaggerConfig()
...
}
}
Congratulations, now you've harnessed the power of extension methods.
Every developer needs some fuel and coffee is mine
I hope you enjoyed this article.
Top comments (3)
don't know why I didn't think of this, I had a story to tidy up startup.cs because it had more than 100 lines of code, searched and I landed here. Thanks.
Thank you for your approach. Little advice: In your extension methods for first parameter 'this' keyword is missing. ;)
Thanks for the heads up