DEV Community

Gaurav
Gaurav

Posted on

7

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

Billboard image

The fastest way to detect downtimes

Join Vercel, CrowdStrike, and thousands of other teams that trust Checkly to streamline monitoring.

Get started now

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.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

πŸ‘‹ Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay