using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; // 用于泛型 ILogger<>
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("📋 加载视频流目标: {Count} 个", netTargets.Count);
if (netTargets.Count > 0)
logger.Debug("🔍 视频流目标详情: {@Targets}", netTargets);
services.AddSingleton>(netTargets);
services.AddHostedService();
// 动态注册 Sender Worker
foreach (var target in netTargets)
{
// 注意:这里需要使用 Microsoft.Extensions.Logging.ILogger 来适配构造函数
services.AddHostedService(sp =>
new GrpcSenderWorker(target, sp.GetRequiredService>()));
}
}
#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
}