DEV Community

Gaurav
Gaurav

Posted on

9

Dependency Injection in ASP.NET Core with Extension Classes: A Comprehensive Guide

Dependency Injection (DI) is a fundamental design pattern in ASP.NET Core that promotes code reusability, maintainability, and testability. One of the best practices for organizing DI in large applications is to encapsulate service registrations using extension classes. This blog post will guide you through the use of DI with extension classes, using the provided example code for a hands-on understanding.

What is Dependency Injection?

Dependency Injection is a design pattern used to achieve Inversion of Control (IoC) between classes and their dependencies. Instead of instantiating objects directly within a class, dependencies are injected, typically during runtime. This makes the application more modular and easier to test.

Benefits of Using Extension Classes for DI

Separation of Concerns: Keeps the Program.cs or Startup.cs clean and manageable.
Reusability: Allows encapsulation of DI logic for reuse across projects.
Maintainability: Changes to service registrations can be made in one place without cluttering the main application configuration.

Example: Dependency Injection Using an Extension Class

Here’s a complete example of using an extension class for DI in ASP.NET Core.

1. Add the Required NuGet Package
Make sure you have the required package installed:

dotnet add package Microsoft.Extensions.DependencyInjection.Abstractions

2. Creating the Extension Class
The extension class encapsulates service registrations for better organization. Below is a class named AddDependencyInjection in the DependencyInjection namespace:

using Microsoft.Extensions.DependencyInjection;
using dumdum.Interface;
using dumdum.Model.DB;
using dumdum.Service.Implementation;
using dumdum.Service.Interface;
using Sieve.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using System.Text;
using Microsoft.IdentityModel.Tokens;

namespace dumdum.DependencyInjection
{
    public static class AddDependencyInjection
    {
        public static IServiceCollection AddDependencies(this IServiceCollection services)
        {
            // Database Context
            services.AddDbContext<Context>(options =>
                options.UseSqlServer(Environment.GetEnvironmentVariable("CodeXMinioService")));

            // General Services
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
            services.AddScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped(typeof(IBaseService<,>), typeof(BaseService<,>));
            services.AddScoped<ISieveProcessor, SieveProcessor>();
            services.AddScoped<ISQLORMService, DapperORMService>();

            // Business Logic Services
            services.AddScoped<IUploadService, UploadService>();
            services.AddScoped<IUserMaster, UserMasterService>();

            // JWT Authentication
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("your_secret_key_here")),
                        ValidateIssuer = false,
                        ValidateAudience = false,
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.Zero
                    };
                });

            return services;
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

3. Using the Extension Method in Program.cs
With the extension class in place, the DI registrations can be easily included in the main entry point of your application:

using dumdum.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

builder.Services.AddDependencies(); // Adding dependencies via extension method

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the middleware pipeline
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

Enter fullscreen mode Exit fullscreen mode

Key Points in the Example

Encapsulation of Services: All the service registrations are encapsulated in the AddDependencies method, promoting reusability and maintainability.
Modular Approach: Each type of service (e.g., DbContext, repositories, business logic services) is grouped logically.
JWT Authentication: Secure your API by configuring AddJwtBearer with token validation parameters.

Benefits of the Approach

Scalability: Easily add more services to the extension method as your application grows.
Code Organization: Keeps DI logic separate from application startup code.
Testability: Simplifies unit testing by providing a centralized place to mock services.

Conclusion

Using extension methods for dependency injection is a best practice in ASP.NET Core that enhances code modularity and readability. By encapsulating service registrations in an extension class, you can keep your main application file clean while making the DI setup reusable and easy to maintain.

Adopting this pattern in your projects will lead to more structured and professional code. Happy coding! 🚀

Connect with me:@LinkedIn

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how they’re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (1)

Collapse
 
stevsharp profile image
Spyros Ponaris

I will also highlight why selecting the right service lifetime ( Scoped, Transient, or Singleton) is critical when designing services with Dependency Injection (DI). Understanding their differences ensures your application maintains optimal performance, avoids unexpected behavior, and supports scalability.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay