DEV Community

Gaurav
Gaurav

Posted on

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

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.