using GFramework.Core.Abstractions.Logging;
using GFramework.Cqrs.Abstractions.Cqrs;
namespace GFramework.Cqrs.Internal;
///
/// 默认的 CQRS 程序集注册协调器。
///
///
/// 该实现把“按稳定程序集键去重”和“委托给 handler registrar 执行实际映射注册”收敛到 CQRS runtime 内部,
/// 避免外层容器继续了解 handler 注册流水线的内部结构。
///
/// 该类型不是线程安全的。调用方应在外部同步边界内访问 ,
/// 例如由容器写锁串行化程序集注册流程。
///
///
internal sealed class DefaultCqrsRegistrationService(ICqrsHandlerRegistrar registrar, ILogger logger)
: ICqrsRegistrationService
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
private readonly HashSet _registeredAssemblyKeys = new(StringComparer.Ordinal);
private readonly ICqrsHandlerRegistrar _registrar = registrar ?? throw new ArgumentNullException(nameof(registrar));
///
/// 注册指定程序集中的 CQRS handlers。
///
/// 要接入的程序集集合。
public void RegisterHandlers(IEnumerable assemblies)
{
ArgumentNullException.ThrowIfNull(assemblies);
var processedAssemblyKeys = new HashSet(StringComparer.Ordinal);
foreach (var assembly in assemblies
.Where(static assembly => assembly is not null)
.OrderBy(GetAssemblyRegistrationKey, StringComparer.Ordinal))
{
var assemblyKey = GetAssemblyRegistrationKey(assembly);
if (!processedAssemblyKeys.Add(assemblyKey))
continue;
if (_registeredAssemblyKeys.Contains(assemblyKey))
{
_logger.Debug(
$"Skipping CQRS handler registration for assembly {assemblyKey} because it was already registered.");
continue;
}
_registrar.RegisterHandlers([assembly]);
_registeredAssemblyKeys.Add(assemblyKey);
}
}
///
/// 生成稳定程序集键,避免相同程序集被不同 实例重复接入。
///
/// 目标程序集。
/// 稳定的程序集标识。
private static string GetAssemblyRegistrationKey(Assembly assembly)
{
return assembly.FullName ?? assembly.GetName().Name ?? assembly.ToString();
}
}