Организация регистраций: extension-методы, модули

↑ 3.2 Dependency Injection · ← Предыдущая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Про поддерживаемость: как не превратить Program.cs в 500 строк регистраций.

Объяснение

Каждый модуль (слой, фича, библиотека) предоставляет extension-метод на IServiceCollection, а Program.cs только вызывает их.

public static class OrdersModule
{
    public static IServiceCollection AddOrders(this IServiceCollection services, IConfiguration cfg)
    {
        services.AddScoped<IOrderService, OrderService>();
        services.AddScoped<IOrderRepository, OrderRepository>();
        services.AddOptions<OrdersOptions>().Bind(cfg.GetSection("Orders")).ValidateOnStart();
        return services;
    }
 
    public static IEndpointRouteBuilder MapOrders(this IEndpointRouteBuilder app)
    {
        var g = app.MapGroup("/orders");
        g.MapGet("{id:guid}", (Guid id, IOrderService s) => s.GetAsync(id));
        return app;
    }
}
 
// Program.cs
builder.Services.AddOrders(builder.Configuration).AddPayments(builder.Configuration);
app.MapOrders();
ПодходПлюсыМинусы
Extension-методы AddXxxпросто, стандарт платформынужно вызывать вручную
Сканирование сборок (Scrutor, конвенции)меньше коданеявно, сложно отлаживать
Модули с интерфейсом IModuleединообразиелишний уровень абстракции

Соглашение: AddXxx — регистрации, UseXxx — middleware, MapXxx — endpoints.

Нюансы и подводные камни

  • Сканирование всех классов по суффиксу «Service» регистрирует лишнее.
  • Порядок регистрации влияет на перезапись сервисов.
  • Модуль не должен читать IConfiguration напрямую при каждом вызове; передавайте секцию или Options.
  • Для тестов оставляйте возможность заменить сервисы через ConfigureTestServices.

Практика

  1. Разнесите регистрации проекта по модулям AddXxx.
  2. Добавьте MapGroup с общим префиксом и авторизацией.
  3. Напишите тест, проверяющий, что все зависимости разрешаются (ValidateOnBuild).

Вопросы с ответами

Связанные темы