You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
6.0 KiB

using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace CellularManagement.WebSocket.Pipeline;
/// <summary>
/// 管道构建器
/// 用于构建消息处理管道
/// </summary>
/// <typeparam name="TInput">输入消息类型</typeparam>
/// <typeparam name="TOutput">输出消息类型</typeparam>
public class PipelineBuilder<TInput, TOutput>
{
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger<PipelineBuilder<TInput, TOutput>> _logger;
private readonly List<IPipelineStep<TInput, TOutput>> _steps = new();
public PipelineBuilder(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
_logger = loggerFactory.CreateLogger<PipelineBuilder<TInput, TOutput>>();
_logger.LogInformation("初始化管道构建器,输入类型:{InputType},输出类型:{OutputType}",
typeof(TInput).Name, typeof(TOutput).Name);
}
/// <summary>
/// 添加处理步骤
/// </summary>
/// <param name="step">处理步骤</param>
/// <returns>管道构建器</returns>
public PipelineBuilder<TInput, TOutput> AddStep(IPipelineStep<TInput, TOutput> step)
{
_logger.LogInformation("添加处理步骤,步骤类型:{StepType}", step.GetType().Name);
_steps.Add(step);
return this;
}
/// <summary>
/// 构建处理管道
/// </summary>
/// <returns>处理管道</returns>
public IPipelineStep<TInput, TOutput> Build()
{
_logger.LogInformation("开始构建处理管道,步骤数量:{StepCount}", _steps.Count);
if (_steps.Count == 0)
{
_logger.LogWarning("处理管道没有添加任何步骤");
throw new InvalidOperationException("处理管道必须至少包含一个步骤");
}
// 构建处理链
var pipeline = _steps[0];
for (int i = 1; i < _steps.Count; i++)
{
var currentStep = _steps[i];
_logger.LogDebug("连接处理步骤:{CurrentStep} -> {NextStep}",
pipeline.GetType().Name, currentStep.GetType().Name);
pipeline = new ChainedPipelineStep(pipeline, currentStep, _loggerFactory);
}
_logger.LogInformation("处理管道构建完成,总步骤数:{StepCount}", _steps.Count);
return pipeline;
}
/// <summary>
/// 链式处理步骤
/// 用于连接多个处理步骤
/// </summary>
private class ChainedPipelineStep : IPipelineStep<TInput, TOutput>
{
private readonly IPipelineStep<TInput, TOutput> _first;
private readonly IPipelineStep<TInput, TOutput> _second;
private readonly ILogger<ChainedPipelineStep> _logger;
public ChainedPipelineStep(
IPipelineStep<TInput, TOutput> first,
IPipelineStep<TInput, TOutput> second,
ILoggerFactory loggerFactory)
{
_first = first;
_second = second;
_logger = loggerFactory.CreateLogger<ChainedPipelineStep>();
_logger.LogDebug("创建链式处理步骤,第一步:{FirstStep},第二步:{SecondStep}",
first.GetType().Name, second.GetType().Name);
}
public async Task<TOutput> ProcessAsync(TInput input, CancellationToken cancellationToken)
{
_logger.LogDebug("开始链式处理消息");
var intermediate = await _first.ProcessAsync(input, cancellationToken);
if (intermediate is TInput inputValue)
{
return await _second.ProcessAsync(inputValue, cancellationToken);
}
throw new InvalidOperationException($"无法将类型 {intermediate?.GetType().Name ?? "null"} 转换为 {typeof(TInput).Name}");
}
public async Task<TOutput> ProcessWithErrorHandlingAsync(TInput input, CancellationToken cancellationToken)
{
_logger.LogDebug("开始链式处理消息(带错误处理)");
try
{
var intermediate = await _first.ProcessWithErrorHandlingAsync(input, cancellationToken);
if (intermediate is TInput inputValue)
{
return await _second.ProcessWithErrorHandlingAsync(inputValue, cancellationToken);
}
throw new InvalidOperationException($"无法将类型 {intermediate?.GetType().Name ?? "null"} 转换为 {typeof(TInput).Name}");
}
catch (Exception ex)
{
_logger.LogError(ex, "链式处理发生错误");
throw;
}
}
}
}
public class Pipeline<TInput, TOutput> : IPipelineStep<TInput, TOutput>
{
private readonly IReadOnlyList<IPipelineStep<TInput, TOutput>> _steps;
private readonly ILogger<Pipeline<TInput, TOutput>> _logger;
public Pipeline(IReadOnlyList<IPipelineStep<TInput, TOutput>> steps, ILogger<Pipeline<TInput, TOutput>> logger)
{
_steps = steps ?? throw new ArgumentNullException(nameof(steps));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<TOutput> ProcessAsync(TInput input, CancellationToken cancellationToken)
{
TOutput? result = default;
var current = input;
foreach (var step in _steps)
{
result = await step.ProcessAsync(current, cancellationToken);
if (result is TInput nextInput)
{
current = nextInput;
}
else
{
break;
}
}
return result ?? throw new InvalidOperationException("管道处理结果不能为 null");
}
public async Task<TOutput> ProcessWithErrorHandlingAsync(TInput input, CancellationToken cancellationToken)
{
try
{
return await ProcessAsync(input, cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "管道处理发生错误");
throw new PipelineException("管道处理失败", ex);
}
}
}