using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
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();
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));
//}
foreach (var target in netTargets)
{
// Modified: 显式声明局部变量,防止 Lambda 捕获循环变量导致的引用重复
var currentTarget = target;
logger.Information("[DI] 准备启动 Worker 实例: {Name} -> {Url}",
currentTarget.Config.Name, currentTarget.Config.Endpoint);
// 使用工厂模式注册,确保传入的是当前的 currentTarget
services.AddSingleton(sp => new GrpcSenderWorker(currentTarget));
}
}
#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
}