using System.Reflection;
using FluentValidation;
using Microsoft.Extensions.DependencyInjection;
using PnvPanel.Application.Common.Behaviors;
using PnvPanel.Application.Common.Messaging;
namespace PnvPanel.Application;
///
/// Точка регистрации сервисов слоя Application: собственный CQRS-диспетчер (ISender),
/// хендлеры/валидаторы (авто-сканирование сборки) и pipeline behaviors — в порядке выполнения.
///
public static class DependencyInjection
{
public static IServiceCollection AddApplication(this IServiceCollection services)
{
var assembly = typeof(DependencyInjection).Assembly;
services.AddScoped();
RegisterClosedGeneric(services, assembly, typeof(ICommandHandler<,>));
RegisterClosedGeneric(services, assembly, typeof(IQueryHandler<,>));
RegisterClosedGeneric(services, assembly, typeof(IValidator<>));
// Порядок важен: Logging (снаружи) -> Validation -> RequireActivation -> UnitOfWork (ближе к хендлеру).
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(RequireActivationBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(UnitOfWorkBehavior<,>));
return services;
}
private static void RegisterClosedGeneric(IServiceCollection services, Assembly assembly, Type openInterface)
{
var implementations = assembly.GetTypes()
.Where(t => t is { IsClass: true, IsAbstract: false })
.SelectMany(t => t.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == openInterface)
.Select(i => (Service: i, Implementation: t)));
foreach (var (service, implementation) in implementations)
services.AddScoped(service, implementation);
}
}