// Copyright (c) 2025-2026 GeWuYou // SPDX-License-Identifier: Apache-2.0 using GFramework.Core.Abstractions.Ioc; using GFramework.Cqrs.Notification; namespace GFramework.Cqrs.Extensions; /// /// 为 CQRS runtime 提供 notification publisher 策略的组合根注册入口。 /// /// /// 默认 runtime 只会消费一个 实例,因此该扩展类把“选择哪种策略”显式收敛到容器配置阶段。 /// 这些入口应在 runtime 创建前调用;对于走标准 GFramework.Core 启动路径的架构,它们会被 CqrsRuntimeModule 自动复用。 /// public static class NotificationPublisherRegistrationExtensions { /// /// 将指定的 notification publisher 实例注册为当前容器唯一的发布策略。 /// /// 目标依赖注入容器。 /// 要复用的 notification publisher 实例。 /// 同一个 ,便于在组合根中继续链式配置。 /// /// 。 /// /// /// 当前容器已存在 注册,无法再切换为另一个策略。 /// public static IIocContainer UseNotificationPublisher( this IIocContainer container, INotificationPublisher notificationPublisher) { ArgumentNullException.ThrowIfNull(container); ArgumentNullException.ThrowIfNull(notificationPublisher); ThrowIfNotificationPublisherAlreadyRegistered(container); container.Register(notificationPublisher); return container; } /// /// 将指定类型的 notification publisher 注册为当前容器唯一的发布策略。 /// /// 发布策略实现类型。 /// 目标依赖注入容器。 /// 同一个 ,便于在组合根中继续链式配置。 /// /// /// 当前容器已存在 注册,无法再切换为另一个策略。 /// public static IIocContainer UseNotificationPublisher(this IIocContainer container) where TNotificationPublisher : class, INotificationPublisher { ArgumentNullException.ThrowIfNull(container); ThrowIfNotificationPublisherAlreadyRegistered(container); container.RegisterSingleton(); return container; } /// /// 将内置 注册为当前容器唯一的 notification publisher 策略。 /// /// 目标依赖注入容器。 /// 同一个 ,便于在组合根中继续链式配置。 /// /// /// 当前容器已存在 注册,无法再切换为另一个策略。 /// /// /// 该策略更适合“等待所有处理器完成并统一观察失败”的语义诉求; /// 若只是为了降低 steady-state publish 开销,应先结合实际 benchmark 结果评估是否值得切换。 /// public static IIocContainer UseTaskWhenAllNotificationPublisher(this IIocContainer container) { return UseNotificationPublisher(container, new TaskWhenAllNotificationPublisher()); } /// /// 将内置 注册为当前容器唯一的 notification publisher 策略。 /// /// 目标依赖注入容器。 /// 同一个 ,便于在组合根中继续链式配置。 /// /// /// 当前容器已存在 注册,无法再切换为另一个策略。 /// /// /// 该策略适合处理器之间存在顺序依赖,或调用方希望在首个失败处立即停止后续分发的场景。 /// public static IIocContainer UseSequentialNotificationPublisher(this IIocContainer container) { return UseNotificationPublisher(container, new SequentialNotificationPublisher()); } /// /// 在组合根阶段阻止多个 notification publisher 策略同时注册,避免 runtime 创建时出现歧义。 /// /// 当前正在配置的依赖注入容器。 /// 当前容器已存在 notification publisher 注册。 private static void ThrowIfNotificationPublisherAlreadyRegistered(IIocContainer container) { if (!container.HasRegistration(typeof(INotificationPublisher))) { return; } throw new InvalidOperationException( $"An {typeof(INotificationPublisher).FullName} is already registered. Remove the existing notification publisher strategy before calling {nameof(UseNotificationPublisher)} again."); } }