diff --git a/GFramework.Core.Abstractions/Logging/LoggerFactoryResolver.cs b/GFramework.Core.Abstractions/Logging/LoggerFactoryResolver.cs
new file mode 100644
index 00000000..a87a18da
--- /dev/null
+++ b/GFramework.Core.Abstractions/Logging/LoggerFactoryResolver.cs
@@ -0,0 +1,250 @@
+namespace GFramework.Core.Abstractions.Logging;
+
+///
+/// 提供全局日志工厂访问入口。
+///
+///
+/// 该类型位于抽象层,是为了让上层模块可以在不依赖 GFramework.Core 实现程序集的前提下
+/// 获取日志记录器。默认 provider 会优先通过反射解析 GFramework.Core 中的控制台实现,
+/// 若宿主未加载该程序集,则退回到静默 provider,避免抽象层形成实现层循环依赖。
+///
+public static class LoggerFactoryResolver
+{
+ private const string DefaultProviderTypeName =
+ "GFramework.Core.Logging.ConsoleLoggerFactoryProvider, GFramework.Core";
+
+ ///
+ /// 获取或设置当前日志工厂提供程序。
+ ///
+ ///
+ /// 当赋值为 时抛出。
+ ///
+ public static ILoggerFactoryProvider Provider
+ {
+ get => field ??= CreateDefaultProvider();
+ set => field = value ?? throw new ArgumentNullException(nameof(value));
+ }
+
+ ///
+ /// 获取或设置新创建日志记录器的最小日志级别。
+ ///
+ ///
+ /// 该属性直接代理到当前 ,确保调用方调整级别后立即影响后续创建的日志器。
+ ///
+ public static LogLevel MinLevel
+ {
+ get => Provider.MinLevel;
+ set => Provider.MinLevel = value;
+ }
+
+ private static ILoggerFactoryProvider CreateDefaultProvider()
+ {
+ if (Type.GetType(DefaultProviderTypeName, throwOnError: false) is { } providerType &&
+ Activator.CreateInstance(providerType) is ILoggerFactoryProvider provider)
+ {
+ provider.MinLevel = LogLevel.Info;
+ return provider;
+ }
+
+ return new SilentLoggerFactoryProvider();
+ }
+
+ ///
+ /// 当宿主未提供默认日志实现时使用的静默 provider。
+ ///
+ private sealed class SilentLoggerFactoryProvider : ILoggerFactoryProvider
+ {
+ public LogLevel MinLevel { get; set; } = LogLevel.Info;
+
+ public ILogger CreateLogger(string name)
+ {
+ return new SilentLogger(name);
+ }
+ }
+
+ ///
+ /// 默认日志实现不可用时的 no-op 日志器。
+ ///
+ private sealed class SilentLogger(string name) : ILogger
+ {
+ public string Name()
+ {
+ return name;
+ }
+
+ public bool IsTraceEnabled()
+ {
+ return false;
+ }
+
+ public bool IsDebugEnabled()
+ {
+ return false;
+ }
+
+ public bool IsInfoEnabled()
+ {
+ return false;
+ }
+
+ public bool IsWarnEnabled()
+ {
+ return false;
+ }
+
+ public bool IsErrorEnabled()
+ {
+ return false;
+ }
+
+ public bool IsFatalEnabled()
+ {
+ return false;
+ }
+
+ public bool IsEnabledForLevel(LogLevel level)
+ {
+ return false;
+ }
+
+ public void Trace(string msg)
+ {
+ }
+
+ public void Trace(string format, object arg)
+ {
+ }
+
+ public void Trace(string format, object arg1, object arg2)
+ {
+ }
+
+ public void Trace(string format, params object[] arguments)
+ {
+ }
+
+ public void Trace(string msg, Exception t)
+ {
+ }
+
+ public void Debug(string msg)
+ {
+ }
+
+ public void Debug(string format, object arg)
+ {
+ }
+
+ public void Debug(string format, object arg1, object arg2)
+ {
+ }
+
+ public void Debug(string format, params object[] arguments)
+ {
+ }
+
+ public void Debug(string msg, Exception t)
+ {
+ }
+
+ public void Info(string msg)
+ {
+ }
+
+ public void Info(string format, object arg)
+ {
+ }
+
+ public void Info(string format, object arg1, object arg2)
+ {
+ }
+
+ public void Info(string format, params object[] arguments)
+ {
+ }
+
+ public void Info(string msg, Exception t)
+ {
+ }
+
+ public void Warn(string msg)
+ {
+ }
+
+ public void Warn(string format, object arg)
+ {
+ }
+
+ public void Warn(string format, object arg1, object arg2)
+ {
+ }
+
+ public void Warn(string format, params object[] arguments)
+ {
+ }
+
+ public void Warn(string msg, Exception t)
+ {
+ }
+
+ public void Error(string msg)
+ {
+ }
+
+ public void Error(string format, object arg)
+ {
+ }
+
+ public void Error(string format, object arg1, object arg2)
+ {
+ }
+
+ public void Error(string format, params object[] arguments)
+ {
+ }
+
+ public void Error(string msg, Exception t)
+ {
+ }
+
+ public void Fatal(string msg)
+ {
+ }
+
+ public void Fatal(string format, object arg)
+ {
+ }
+
+ public void Fatal(string format, object arg1, object arg2)
+ {
+ }
+
+ public void Fatal(string format, params object[] arguments)
+ {
+ }
+
+ public void Fatal(string msg, Exception t)
+ {
+ }
+
+ public void Log(LogLevel level, string message)
+ {
+ }
+
+ public void Log(LogLevel level, string format, object arg)
+ {
+ }
+
+ public void Log(LogLevel level, string format, object arg1, object arg2)
+ {
+ }
+
+ public void Log(LogLevel level, string format, params object[] arguments)
+ {
+ }
+
+ public void Log(LogLevel level, string message, Exception exception)
+ {
+ }
+ }
+}
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs
index 583c30c8..f6cbdafa 100644
--- a/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs
+++ b/GFramework.Core.Tests/Architectures/ArchitectureComponentRegistryBehaviorTests.cs
@@ -1,11 +1,11 @@
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Enums;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Architectures;
using GFramework.Core.Logging;
-using Microsoft.Extensions.DependencyInjection;
namespace GFramework.Core.Tests.Architectures;
@@ -714,4 +714,4 @@ public class ArchitectureComponentRegistryBehaviorTests
return _context;
}
}
-}
\ No newline at end of file
+}
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
index 87978cd2..cdcde44d 100644
--- a/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
+++ b/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
@@ -5,6 +5,7 @@ using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Enums;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Ioc;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Query;
using GFramework.Core.Abstractions.Systems;
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs
index 717e1b18..10945ad2 100644
--- a/GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs
+++ b/GFramework.Core.Tests/Architectures/ArchitectureInitializationPipelineTests.cs
@@ -1,9 +1,9 @@
using GFramework.Core.Abstractions.Enums;
using GFramework.Core.Abstractions.Events;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Architectures;
using GFramework.Core.Environment;
using GFramework.Core.Logging;
-using Microsoft.Extensions.DependencyInjection;
namespace GFramework.Core.Tests.Architectures;
@@ -185,4 +185,4 @@ public class ArchitectureInitializationPipelineTests
private sealed class BootstrapMarker
{
}
-}
\ No newline at end of file
+}
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
index b0ef7262..943e2bfd 100644
--- a/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
+++ b/GFramework.Core.Tests/Architectures/ArchitectureLifecycleBehaviorTests.cs
@@ -2,12 +2,12 @@ using System.Reflection;
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Enums;
using GFramework.Core.Abstractions.Lifecycle;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Architectures;
using GFramework.Core.Logging;
-using Microsoft.Extensions.DependencyInjection;
namespace GFramework.Core.Tests.Architectures;
@@ -460,4 +460,4 @@ public class ArchitectureLifecycleBehaviorTests
return _context;
}
}
-}
\ No newline at end of file
+}
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
index cfe0db79..493f3590 100644
--- a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
+++ b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs
@@ -1,4 +1,5 @@
using GFramework.Core.Abstractions.Architectures;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Architectures;
using GFramework.Core.Logging;
diff --git a/GFramework.Core.Tests/Architectures/PriorityServiceTests.cs b/GFramework.Core.Tests/Architectures/PriorityServiceTests.cs
index 24fd2681..0499a4ab 100644
--- a/GFramework.Core.Tests/Architectures/PriorityServiceTests.cs
+++ b/GFramework.Core.Tests/Architectures/PriorityServiceTests.cs
@@ -1,5 +1,6 @@
using System.Reflection;
using GFramework.Core.Abstractions.Bases;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
@@ -244,4 +245,4 @@ public class PriorityTestUtilityC : IPriorityTestUtility, IPrioritized
public int Priority => 30;
}
-#endregion
\ No newline at end of file
+#endregion
diff --git a/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs b/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
index 0e03059e..4104ccb1 100644
--- a/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
+++ b/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
@@ -1,6 +1,7 @@
using System.Reflection;
using GFramework.Core.Abstractions.Bases;
using GFramework.Core.Abstractions.Cqrs;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Ioc;
using GFramework.Core.Logging;
using GFramework.Core.Tests.Cqrs;
diff --git a/GFramework.Core.Tests/State/StateMachineSystemTests.cs b/GFramework.Core.Tests/State/StateMachineSystemTests.cs
index 0ea62de6..2c234238 100644
--- a/GFramework.Core.Tests/State/StateMachineSystemTests.cs
+++ b/GFramework.Core.Tests/State/StateMachineSystemTests.cs
@@ -1,5 +1,6 @@
using System.Reflection;
using GFramework.Core.Abstractions.Enums;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.State;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Architectures;
@@ -373,4 +374,4 @@ public class TestStateV5_2 : IState
}
}
-#endregion
\ No newline at end of file
+#endregion
diff --git a/GFramework.Core/Logging/LoggerFactoryResolver.cs b/GFramework.Core/Logging/LoggerFactoryResolver.cs
deleted file mode 100644
index c15378d1..00000000
--- a/GFramework.Core/Logging/LoggerFactoryResolver.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using GFramework.Core.Abstractions.Logging;
-
-namespace GFramework.Core.Logging;
-
-///
-/// 日志工厂提供程序解析器,用于管理和提供日志工厂提供程序实例
-///
-public static class LoggerFactoryResolver
-{
- ///
- /// 获取或设置当前的日志工厂提供程序
- ///
- ///
- /// 日志工厂提供程序实例,默认为控制台日志工厂提供程序
- ///
- public static ILoggerFactoryProvider Provider { get; set; }
- = new ConsoleLoggerFactoryProvider();
-
- ///
- /// 获取或设置日志记录的最小级别
- ///
- ///
- /// 日志级别枚举值,默认为Info级别
- ///
- public static LogLevel MinLevel { get; set; } = LogLevel.Info;
-}
\ No newline at end of file
diff --git a/GFramework.Core/Properties/TypeForwarders.cs b/GFramework.Core/Properties/TypeForwarders.cs
new file mode 100644
index 00000000..a71d9af2
--- /dev/null
+++ b/GFramework.Core/Properties/TypeForwarders.cs
@@ -0,0 +1,4 @@
+using System.Runtime.CompilerServices;
+using GFramework.Core.Abstractions.Logging;
+
+[assembly: TypeForwardedTo(typeof(LoggerFactoryResolver))]
diff --git a/GFramework.Core/Services/Modules/CqrsRuntimeModule.cs b/GFramework.Core/Services/Modules/CqrsRuntimeModule.cs
index 9e7ad307..3fe37558 100644
--- a/GFramework.Core/Services/Modules/CqrsRuntimeModule.cs
+++ b/GFramework.Core/Services/Modules/CqrsRuntimeModule.cs
@@ -1,7 +1,7 @@
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Ioc;
-using GFramework.Core.Logging;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs;
diff --git a/GFramework.Cqrs.Tests/GlobalUsings.cs b/GFramework.Cqrs.Tests/GlobalUsings.cs
index c47473b0..9f52a3dd 100644
--- a/GFramework.Cqrs.Tests/GlobalUsings.cs
+++ b/GFramework.Cqrs.Tests/GlobalUsings.cs
@@ -20,6 +20,7 @@ global using System.Reflection;
global using System.Runtime.CompilerServices;
global using System.Threading;
global using System.Threading.Tasks;
+global using System.Diagnostics;
global using GFramework.Tests.Common;
global using Microsoft.Extensions.DependencyInjection;
global using Moq;
diff --git a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs b/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs
index 257809f0..fe8f4413 100644
--- a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs
+++ b/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs
@@ -1,3 +1,4 @@
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Architectures;
using GFramework.Core.Ioc;
using GFramework.Core.Logging;
diff --git a/GFramework.Cqrs.Tests/Mediator/MediatorArchitectureIntegrationTests.cs b/GFramework.Cqrs.Tests/Mediator/MediatorArchitectureIntegrationTests.cs
index e403735e..728f005a 100644
--- a/GFramework.Cqrs.Tests/Mediator/MediatorArchitectureIntegrationTests.cs
+++ b/GFramework.Cqrs.Tests/Mediator/MediatorArchitectureIntegrationTests.cs
@@ -1,4 +1,5 @@
using GFramework.Core.Abstractions.Architectures;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Architectures;
using GFramework.Core.Command;
using GFramework.Core.Ioc;
diff --git a/GFramework.Cqrs.Tests/Mediator/MediatorComprehensiveTests.cs b/GFramework.Cqrs.Tests/Mediator/MediatorComprehensiveTests.cs
index b0b510d6..423b1c9b 100644
--- a/GFramework.Cqrs.Tests/Mediator/MediatorComprehensiveTests.cs
+++ b/GFramework.Cqrs.Tests/Mediator/MediatorComprehensiveTests.cs
@@ -1,5 +1,6 @@
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Events;
+using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Architectures;
using GFramework.Core.Command;
using GFramework.Core.Environment;
diff --git a/GFramework.Core/Cqrs/Behaviors/LoggingBehavior.cs b/GFramework.Cqrs/Cqrs/Behaviors/LoggingBehavior.cs
similarity index 71%
rename from GFramework.Core/Cqrs/Behaviors/LoggingBehavior.cs
rename to GFramework.Cqrs/Cqrs/Behaviors/LoggingBehavior.cs
index 7230f53d..ccd9f0bf 100644
--- a/GFramework.Core/Cqrs/Behaviors/LoggingBehavior.cs
+++ b/GFramework.Cqrs/Cqrs/Behaviors/LoggingBehavior.cs
@@ -11,19 +11,20 @@
// 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 GFramework.Cqrs.Abstractions.Cqrs;
-namespace GFramework.Core.Cqrs.Behaviors;
+namespace GFramework.Cqrs.Cqrs.Behaviors;
///
-/// 日志记录行为类,用于在CQRS管道中记录请求处理的日志信息
-/// 实现IPipelineBehavior接口,为请求处理提供日志记录功能
+/// 在 CQRS 请求管道中记录请求开始、完成、取消与失败日志。
///
-/// 请求类型,必须实现IRequest接口
-/// 响应类型
+/// 请求类型。
+/// 响应类型。
+///
+/// 该行为保留在 GFramework.Core.Cqrs.Behaviors 命名空间以兼容现有调用点,
+/// 但实现已迁入 GFramework.Cqrs 程序集,避免继续由 GFramework.Core 承载 CQRS runtime 细节。
+///
public sealed class LoggingBehavior : IPipelineBehavior
where TRequest : IRequest
{
@@ -31,13 +32,12 @@ public sealed class LoggingBehavior : IPipelineBehavior));
///
- /// 处理请求并记录日志
- /// 在请求处理前后记录调试信息,处理异常时记录错误日志
+ /// 执行日志包装后的下一段请求处理逻辑。
///
- /// 要处理的请求消息
- /// 下一个处理委托,用于继续管道执行
- /// 取消令牌,用于取消操作
- /// 处理结果的ValueTask
+ /// 当前请求消息。
+ /// 后续处理委托。
+ /// 取消令牌。
+ /// 请求处理结果。
public async ValueTask Handle(
TRequest message,
MessageHandlerDelegate next,
diff --git a/GFramework.Core/Cqrs/Behaviors/PerformanceBehavior.cs b/GFramework.Cqrs/Cqrs/Behaviors/PerformanceBehavior.cs
similarity index 61%
rename from GFramework.Core/Cqrs/Behaviors/PerformanceBehavior.cs
rename to GFramework.Cqrs/Cqrs/Behaviors/PerformanceBehavior.cs
index 35ab2978..1d13319d 100644
--- a/GFramework.Core/Cqrs/Behaviors/PerformanceBehavior.cs
+++ b/GFramework.Cqrs/Cqrs/Behaviors/PerformanceBehavior.cs
@@ -11,33 +11,34 @@
// 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 GFramework.Cqrs.Abstractions.Cqrs;
-namespace GFramework.Core.Cqrs.Behaviors;
+namespace GFramework.Cqrs.Cqrs.Behaviors;
///
-/// 性能监控行为类,用于监控CQRS请求的执行时间
-/// 实现IPipelineBehavior接口,检测并记录执行时间过长的请求
+/// 在 CQRS 请求管道中监控处理耗时,并对长耗时请求发出告警。
///
-/// 请求类型,必须实现IRequest接口
-/// 响应类型
+/// 请求类型。
+/// 响应类型。
+///
+/// 该行为保留现有公开命名空间以维持消费端兼容性,但实现已迁入 GFramework.Cqrs 程序集。
+///
public sealed class PerformanceBehavior : IPipelineBehavior
where TRequest : IRequest
{
+ private const double SlowRequestThresholdMilliseconds = 500;
+
private readonly ILogger _logger =
LoggerFactoryResolver.Provider.CreateLogger(nameof(PerformanceBehavior));
///
- /// 处理请求并监控执行时间
- /// 使用Stopwatch测量请求处理耗时,超过500ms时记录警告日志
+ /// 统计当前请求处理耗时,并在超阈值时记录警告日志。
///
- /// 要处理的请求消息
- /// 下一个处理委托,用于继续管道执行
- /// 取消令牌,用于取消操作
- /// 处理结果的ValueTask
+ /// 当前请求消息。
+ /// 后续处理委托。
+ /// 取消令牌。
+ /// 请求处理结果。
public async ValueTask Handle(
TRequest message,
MessageHandlerDelegate next,
@@ -53,11 +54,10 @@ public sealed class PerformanceBehavior : IPipelineBehavior
{
var elapsed = Stopwatch.GetElapsedTime(start);
- if (elapsed.TotalMilliseconds > 500)
+ if (elapsed.TotalMilliseconds > SlowRequestThresholdMilliseconds)
{
var requestName = typeof(TRequest).Name;
- _logger.Warn(
- $"Long Running Request: {requestName} ({elapsed.TotalMilliseconds:F2} ms)");
+ _logger.Warn($"Long Running Request: {requestName} ({elapsed.TotalMilliseconds:F2} ms)");
}
}
}
diff --git a/GFramework.Cqrs/GlobalUsings.cs b/GFramework.Cqrs/GlobalUsings.cs
index 7f8c14d6..97f2d13a 100644
--- a/GFramework.Cqrs/GlobalUsings.cs
+++ b/GFramework.Cqrs/GlobalUsings.cs
@@ -4,3 +4,4 @@ global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using Microsoft.Extensions.DependencyInjection;
+global using System.Diagnostics;