Search code examples
c#design-patternsarchitectureclean-architecture

How to register Infrastructure layer dependencies in Clean Architecture using .NET 6?


I am implementing a project using Clean Architecture in .NET 6. As per the Clean Architecture principle we should not reference Infrastructure layer in Web Api(Presentation layer), we should only access Application layer in Web Api.

So how can I register Infrastructure layer's dependencies without violating the Clean Architecture principle? I have created below extension method in Infrastructure layer to register dependencies:

namespace JwtWithIdentityDemo.Infrastructure.IoC
{
    public static class RegisterInfrastructure
    {
        public static void AddInfrastructure(this IServiceCollection services,
            IConfiguration configuration)
        {
            services.Configure<JwtSetings>(configuration.GetSection(JwtSetings.SectionName));
            services.AddSingleton<IJwtTokenGenerator, JwtTokenGenerator>();
            services.AddTransient<IUserManagerWrapper, UserManagerWrapper>();

            // For Identity
            services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.AddScoped<UserManager<IdentityUser>>();

            // For Entity Framework
            services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(configuration.GetConnectionString("JwtWithIdentityDemoDb"),
          sqlServerOptions => sqlServerOptions.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)
              .EnableRetryOnFailure(
                  maxRetryCount: 5,
                  maxRetryDelay: TimeSpan.FromSeconds(30),
                  errorNumbersToAdd: null)
            ),
                ServiceLifetime.Transient
            );

        }

    }
}

If I call AddInfrastructure method in Program.cs then I have to add reference of Infrastructure library, which is violating the Clean Architecture's principles.

var builder = WebApplication.CreateBuilder(args);
{
    builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Program>());

    builder.Services.AddApplication(builder.Configuration);
    builder.Services.AddControllers();

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

    builder.Services.AddInfrastructure(builder.Configuration)

}

Solution

  • I would argue that using AddInfrastructure in the web application project (hence adding link to Infrastructure from it) is not violating the main principle (in my opinion) of the the clean architecture:

    Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in the an inner circle.

    Web API and Infrastructure are concepts of the same level and Program is your composition root.

    If you really want to go purist you can extract actual application-relevant ASP.NET Core code into a separate library and have a separate project for composition root:

    It will introduce a bit more ceremony but not much.

    Also check out this and this github repos.