using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using SHH.CameraSdk; // 确保 namespace 与 Program.cs 的引用一致 namespace SHH.CameraService; public static class ServiceCollectionExtensions { // ======================================================================== // 1. 核心聚合方法 (对应 Program.cs 中的调用) // ======================================================================== #region AddCameraBusinessServices /// /// [聚合] 注册所有核心业务 (包含逻辑处理、SDK、Gateway、视频流) /// public static void AddCameraBusinessServices(this IServiceCollection services, ServiceConfig config, Serilog.ILogger logger) { // 1.1 注册基础业务逻辑 services.AddBusinessServices(config); // 1.2 注册视频流相关 (因为需要 Logger,所以单独传) services.AddStreamTargets(config, logger); } #endregion #region AddBusinessServices /// /// 集中注册 SDK、Workers、Gateway 等纯业务服务 /// private static void AddBusinessServices(this IServiceCollection services, ServiceConfig config) { // 基础单例 services.AddSingleton(config); services.AddSingleton(); // 图像处理集群 services.AddSingleton(sp => new ImageScaleCluster(4, sp.GetRequiredService())); services.AddSingleton(sp => new ImageEnhanceCluster(4, sp.GetRequiredService())); services.AddHostedService(); // SDK 与核心引擎 services.AddCameraSdk(config.NumericId); services.AddHostedService(); // 监控与网关 services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); // 指令分发系统 services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); } #endregion #region AddStreamTargets /// /// 注册视频流目标 (StreamTargets & GrpcSender) /// private static void AddStreamTargets(this IServiceCollection services, ServiceConfig config, Serilog.ILogger logger) { var netTargets = new List(); if (config.VideoEndpoints != null) { foreach (var cfgVideo in config.VideoEndpoints) { netTargets.Add(new StreamTarget(new PushTargetConfig { Name = cfgVideo.Description, Endpoint = cfgVideo.Uri, QueueCapacity = 10, })); } } logger.Information("[Core] 📋 加载视频流目标: {Count} 个", netTargets.Count); if (netTargets.Count > 0) { foreach (var item in netTargets) logger.Debug("[Core] 🔍 视频流目标详情: {@Targets}", new { item.Config }); } services.AddSingleton>(netTargets); services.AddHostedService(); // 动态注册 Sender Worker foreach (var target in netTargets) { // 注意:这里需要使用 Microsoft.Extensions.Logging.ILogger 来适配构造函数 services.AddHostedService(sp => new GrpcSenderWorker(target)); } } #endregion // ======================================================================== // 2. Web 支持与管道 (Program.cs 调用的另外两个方法) // ======================================================================== #region AddWebSupport /// /// 注册 Controller, Swagger, Cors /// public static void AddWebSupport(this IServiceCollection services, ServiceConfig config) { services.AddCors(options => { options.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); // 注册 Controller 并添加过滤器 services.AddControllers(options => { options.Filters.Add(); }) .AddApplicationPart(typeof(CamerasController).Assembly) // 确保能扫描到 Controller .AddApplicationPart(typeof(MonitorController).Assembly); services.AddEndpointsApiExplorer(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = $"SHH Gateway #{config.AppId}", Version = "v1" }); }); } #endregion #region ConfigurePipeline /// /// 配置 HTTP 中间件管道 /// public static void ConfigurePipeline(this WebApplication app, ServiceConfig config) { // 开启 Swagger app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", $"SHH Gateway #{config.AppId}")); // 简单健康检查端点 app.MapGet("/", () => $"SHH Gateway {config.AppId} is running."); app.UseCors("AllowAll"); app.MapControllers(); } #endregion }