using Extensions.Hosting.AsyncInitialization; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Tnsu.ApprovalRoute.Infrastructure.Persistence; using Tnsu.ApprovalRoute.Infrastructure.SharePoint; using Tnsu.ApprovalRoute.Infrastructure.TnsuPortal; namespace Tnsu.ApprovalRoute.Infrastructure; public static class InfrastructureServiceCollectionExtensions { public static IServiceCollection AddApprovalRouteInfrastructure( this IServiceCollection services, IConfiguration configuration) { services.AddHttpContextAccessor(); services.AddDbContext(opt => opt.UseNpgsql(configuration.GetConnectionString("Postgres")) .UseSnakeCaseNamingConvention()); services.AddAsyncInitializer(); services.AddScoped(); services.Configure(configuration.GetSection("SharePoint")); // Провайдер сертификата — синглтон: разобранный .pfx кешируется на всё // время жизни процесса (см. DbCertificateProvider). services.AddSingleton(); services.AddHttpClient(); services.AddScoped(); services.Configure(configuration.GetSection("TnsuPortal")); services.AddHttpClient(); // Токен вызывающего и общая авторизация запросов к порталу — одни на всех // его клиентов (см. TnsuPortalCallerToken/TnsuPortalAuthorizer). Именно // Scoped: Hangfire даёт задаче свою область DI, и положенный в задаче токен // не должен протекать в соседние. services.AddScoped(); services.AddScoped(); // Подписка новых списков на уведомления SharePoint. Клиент отдельный от // ITnsuPortalClient: там кешируемые чтения справочника, здесь команда. // Своих опций нет — адрес приёмника лежит в SharePoint:NotificationUrl. services.AddHttpClient((sp, client) => { var options = sp.GetRequiredService>().Value; client.BaseAddress = new Uri(options.BaseUrl); }); // ITnsuPortalClient резолвится в CachingTnsuPortalClient (кеш на 5 минут, // см. её комментарий) — сам HttpTnsuPortalClient регистрируем по // конкретному типу, а не по интерфейсу, чтобы декоратор мог его получить // как обычную зависимость. services.AddHttpClient((sp, client) => { var options = sp.GetRequiredService>().Value; client.BaseAddress = new Uri(options.BaseUrl); }); services.AddMemoryCache(); services.AddScoped(); return services; } }