diff --git a/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj b/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj index 3068015..580f5dd 100644 --- a/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj +++ b/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj @@ -26,5 +26,9 @@ runtime; build; native; contentfiles; analyzers + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/GFramework.Core.Abstractions/architecture/IArchitecture.cs b/GFramework.Core.Abstractions/architecture/IArchitecture.cs index 8c4e0cf..022201d 100644 --- a/GFramework.Core.Abstractions/architecture/IArchitecture.cs +++ b/GFramework.Core.Abstractions/architecture/IArchitecture.cs @@ -78,6 +78,14 @@ public interface IArchitecture : IAsyncInitializable /// 工具实例创建后的回调函数,可为null void RegisterUtility(Action? onCreated = null) where T : class, IUtility; + /// + /// 注册中介行为管道 + /// 用于配置Mediator框架的行为拦截和处理逻辑 + /// + /// 行为类型,必须是引用类型 + void RegisterMediatorBehavior() + where TBehavior : class; + /// /// 安装架构模块 /// diff --git a/GFramework.Core.Abstractions/architecture/IArchitectureConfiguration.cs b/GFramework.Core.Abstractions/architecture/IArchitectureConfiguration.cs index 3504e47..1050dbc 100644 --- a/GFramework.Core.Abstractions/architecture/IArchitectureConfiguration.cs +++ b/GFramework.Core.Abstractions/architecture/IArchitectureConfiguration.cs @@ -1,4 +1,5 @@ using GFramework.Core.Abstractions.properties; +using Mediator; namespace GFramework.Core.Abstractions.architecture; @@ -16,4 +17,11 @@ public interface IArchitectureConfiguration /// 获取或设置架构选项,包含架构相关的配置参数 /// ArchitectureProperties ArchitectureProperties { get; set; } + + /// + /// 获取或设置Mediator配置委托 + /// 用于自定义Mediator框架的配置选项 + /// + /// 配置Mediator选项的委托函数,可为null + Action? Configurator { get; set; } } \ No newline at end of file diff --git a/GFramework.Core.Abstractions/ioc/IIocContainer.cs b/GFramework.Core.Abstractions/ioc/IIocContainer.cs index 9b092c8..2d3c79d 100644 --- a/GFramework.Core.Abstractions/ioc/IIocContainer.cs +++ b/GFramework.Core.Abstractions/ioc/IIocContainer.cs @@ -1,5 +1,6 @@ using GFramework.Core.Abstractions.rule; using GFramework.Core.Abstractions.system; +using Mediator; using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.Abstractions.ioc; @@ -71,6 +72,21 @@ public interface IIocContainer : IContextAware /// 创建服务实例的工厂委托函数 void RegisterFactory(Func factory) where TService : class; + /// + /// 注册中介行为管道 + /// 用于配置Mediator框架的行为拦截和处理逻辑 + /// + /// 行为类型,必须是引用类型 + void RegisterMediatorBehavior() + where TBehavior : class; + + /// + /// 注册并配置Mediator框架 + /// 提供自定义配置选项来调整Mediator的行为 + /// + /// 可选的配置委托函数,用于自定义Mediator选项 + void RegisterMediator(Action? configurator = null); + #endregion #region Get Methods diff --git a/GFramework.Core/GFramework.Core.csproj b/GFramework.Core/GFramework.Core.csproj index 3897ac1..513b2a8 100644 --- a/GFramework.Core/GFramework.Core.csproj +++ b/GFramework.Core/GFramework.Core.csproj @@ -13,10 +13,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/GFramework.Core/architecture/Architecture.cs b/GFramework.Core/architecture/Architecture.cs index e7a00e3..cc06fa2 100644 --- a/GFramework.Core/architecture/Architecture.cs +++ b/GFramework.Core/architecture/Architecture.cs @@ -10,7 +10,6 @@ using GFramework.Core.Abstractions.utility; using GFramework.Core.environment; using GFramework.Core.extensions; using GFramework.Core.logging; -using Mediator; using Microsoft.Extensions.DependencyInjection; using IDisposable = GFramework.Core.Abstractions.lifecycle.IDisposable; @@ -30,6 +29,17 @@ public abstract class Architecture( { #region Module Management + /// + /// 注册中介行为管道 + /// 用于配置Mediator框架的行为拦截和处理逻辑 + /// + /// 行为类型,必须是引用类型 + public void RegisterMediatorBehavior() where TBehavior : class + { + _logger.Debug($"Registering mediator behavior: {typeof(TBehavior).Name}"); + Container.RegisterPlurality(); + } + /// /// 安装架构模块 /// @@ -627,14 +637,7 @@ public abstract class Architecture( // 为服务设置上下文 Services.SetContext(_context); // 添加 Mediator - Container.Services.AddMediator(options => - { - options.Namespace = "GFramework.Core.Mediator"; - options.ServiceLifetime = ServiceLifetime.Singleton; - options.GenerateTypesAsInternal = true; - options.NotificationPublisherType = typeof(ForeachAwaitPublisher); - }); - + Container.RegisterMediator(Configuration.Configurator); // === 用户 Init === _logger.Debug("Calling user Init()"); Init(); diff --git a/GFramework.Core/architecture/ArchitectureConfiguration.cs b/GFramework.Core/architecture/ArchitectureConfiguration.cs index f431296..1af6a00 100644 --- a/GFramework.Core/architecture/ArchitectureConfiguration.cs +++ b/GFramework.Core/architecture/ArchitectureConfiguration.cs @@ -2,6 +2,8 @@ using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.properties; using GFramework.Core.logging; +using Mediator; +using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.architecture; @@ -32,4 +34,17 @@ public sealed class ArchitectureConfiguration : IArchitectureConfiguration AllowLateRegistration = false, StrictPhaseValidation = true }; + + /// + /// 获取或设置Mediator配置委托 + /// 用于自定义Mediator框架的配置选项 + /// + /// 配置Mediator选项的委托函数,可为null + public Action? Configurator { get; set; } = options => + { + options.Namespace = "GFramework.Core.Mediator"; + options.ServiceLifetime = ServiceLifetime.Singleton; + options.GenerateTypesAsInternal = true; + options.NotificationPublisherType = typeof(ForeachAwaitPublisher); + }; } \ No newline at end of file diff --git a/GFramework.Core/cqrs/behaviors/LoggingBehavior.cs b/GFramework.Core/cqrs/behaviors/LoggingBehavior.cs new file mode 100644 index 0000000..d6bbd7a --- /dev/null +++ b/GFramework.Core/cqrs/behaviors/LoggingBehavior.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2026 GeWuYou +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using GFramework.Core.Abstractions.logging; +using GFramework.Core.logging; +using Mediator; + +namespace GFramework.Core.cqrs.behaviors; + +/// +/// 日志记录行为类,用于在CQRS管道中记录请求处理的日志信息 +/// 实现IPipelineBehavior接口,为请求处理提供日志记录功能 +/// +/// 请求类型,必须实现IRequest接口 +/// 响应类型 +public sealed class LoggingBehavior : IPipelineBehavior + where TRequest : IRequest +{ + private readonly ILogger _logger = + LoggerFactoryResolver.Provider.CreateLogger(nameof(LoggingBehavior)); + + /// + /// 处理请求并记录日志 + /// 在请求处理前后记录调试信息,处理异常时记录错误日志 + /// + /// 要处理的请求消息 + /// 下一个处理委托,用于继续管道执行 + /// 取消令牌,用于取消操作 + /// 处理结果的ValueTask + public ValueTask Handle(TRequest message, MessageHandlerDelegate next, + CancellationToken cancellationToken) + { + var requestName = typeof(TRequest).Name; + + _logger.Debug($"Handling {requestName}"); + + try + { + var response = next(message, cancellationToken); + _logger.Debug($"Handled {requestName} successfully"); + return response; + } + catch (Exception ex) + { + _logger.Error($"Error handling {requestName}", ex); + throw; + } + } +} \ No newline at end of file diff --git a/GFramework.Core/cqrs/behaviors/PerformanceBehavior.cs b/GFramework.Core/cqrs/behaviors/PerformanceBehavior.cs new file mode 100644 index 0000000..f4a4da0 --- /dev/null +++ b/GFramework.Core/cqrs/behaviors/PerformanceBehavior.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2026 GeWuYou +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Diagnostics; +using GFramework.Core.Abstractions.logging; +using GFramework.Core.logging; +using Mediator; + +namespace GFramework.Core.cqrs.behaviors; + +/// +/// 性能监控行为类,用于监控CQRS请求的执行时间 +/// 实现IPipelineBehavior接口,检测并记录执行时间过长的请求 +/// +/// 请求类型,必须实现IRequest接口 +/// 响应类型 +public sealed class PerformanceBehavior : IPipelineBehavior + where TRequest : IRequest +{ + private readonly ILogger _logger = + LoggerFactoryResolver.Provider.CreateLogger(nameof(PerformanceBehavior)); + + /// + /// 处理请求并监控执行时间 + /// 使用Stopwatch测量请求处理耗时,超过500ms时记录警告日志 + /// + /// 要处理的请求消息 + /// 下一个处理委托,用于继续管道执行 + /// 取消令牌,用于取消操作 + /// 处理结果的ValueTask + public ValueTask Handle(TRequest message, MessageHandlerDelegate next, + CancellationToken cancellationToken) + { + var stopwatch = Stopwatch.StartNew(); + + var response = next(message, cancellationToken); + + stopwatch.Stop(); + + var elapsedMilliseconds = stopwatch.ElapsedMilliseconds; + + // 只有当执行时间超过500毫秒时才记录警告日志 + if (elapsedMilliseconds <= 500) return response; + var requestName = typeof(TRequest).Name; + _logger.Warn($"Long Running Request: {requestName} ({elapsedMilliseconds} ms)"); + + return response; + } +} \ No newline at end of file diff --git a/GFramework.Core/ioc/MicrosoftDiContainer.cs b/GFramework.Core/ioc/MicrosoftDiContainer.cs index b0e1ab2..9961f03 100644 --- a/GFramework.Core/ioc/MicrosoftDiContainer.cs +++ b/GFramework.Core/ioc/MicrosoftDiContainer.cs @@ -3,6 +3,7 @@ using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.system; using GFramework.Core.logging; using GFramework.Core.rule; +using Mediator; using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.ioc; @@ -24,12 +25,10 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) /// 当容器已冻结时抛出 private void ThrowIfFrozen() { - if (_frozen) - { - const string errorMsg = "MicrosoftDiContainer is frozen"; - _logger.Error(errorMsg); - throw new InvalidOperationException(errorMsg); - } + if (!_frozen) return; + const string errorMsg = "MicrosoftDiContainer is frozen"; + _logger.Error(errorMsg); + throw new InvalidOperationException(errorMsg); } #endregion @@ -241,6 +240,57 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) Services.AddSingleton(factory); } + /// + /// 注册中介行为管道 + /// 用于配置Mediator框架的行为拦截和处理逻辑 + /// + /// 行为类型,必须是引用类型 + public void RegisterMediatorBehavior() where TBehavior : class + { + _lock.EnterWriteLock(); + try + { + ThrowIfFrozen(); + + Services.AddSingleton( + typeof(IPipelineBehavior<,>), + typeof(TBehavior) + ); + + _logger.Debug($"Mediator behavior registered: {typeof(TBehavior).Name}"); + } + finally + { + _lock.ExitWriteLock(); + } + } + + /// + /// 注册 Mediator(基于 Source Generator) + /// + /// 可选的配置委托 + public void RegisterMediator(Action? configurator = null) + { + _lock.EnterWriteLock(); + try + { + ThrowIfFrozen(); + + // 添加 Mediator + Services.AddMediator(options => + { + // 用户自定义配置 + configurator?.Invoke(options); + }); + + _logger.Info("Mediator registered with Source Generator"); + } + finally + { + _lock.ExitWriteLock(); + } + } + #endregion #region Get