Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace GFramework.Core.Abstractions.Architectures;
/// </summary>
/// <remarks>
/// <para>旧的 <c>GFramework.Core.Abstractions.Command</c> 与 <c>GFramework.Core.Abstractions.Query</c> 契约会继续通过原有 Command/Query Executor 路径执行,以保证存量代码兼容。</para>
/// <para>新的 <c>GFramework.Core.Abstractions.Cqrs</c> 契约由内置 CQRS dispatcher 统一处理,支持 request pipeline、notification publish 与 stream request。</para>
/// <para>新的 <c>GFramework.Cqrs.Abstractions.Cqrs</c> 契约由内置 CQRS dispatcher 统一处理,支持 request pipeline、notification publish 与 stream request。</para>
/// <para>新功能优先使用 <see cref="SendRequestAsync{TResponse}(IRequest{TResponse},CancellationToken)" />、<see cref="SendAsync{TCommand}(TCommand,CancellationToken)" /> 与对应的 CQRS Command/Query 重载;迁移旧代码时可先保留旧入口,再逐步替换为 CQRS 请求模型。</para>
/// </remarks>
public interface IArchitectureContext
Expand Down Expand Up @@ -175,7 +175,7 @@ ValueTask<TResponse> SendCommandAsync<TResponse>(
/// <param name="query">要发送的 CQRS 查询。</param>
/// <returns>查询结果。</returns>
/// <remarks>
/// 这是迁移后的推荐查询入口。新查询应优先实现 <c>GFramework.Core.Abstractions.Cqrs.Query.IQuery&lt;TResponse&gt;</c>。
/// 这是迁移后的推荐查询入口。新查询应优先实现 <c>GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery&lt;TResponse&gt;</c>。
/// </remarks>
TResponse SendQuery<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query);

Expand Down
281 changes: 281 additions & 0 deletions GFramework.Core.Abstractions/Logging/LoggerFactoryResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
namespace GFramework.Core.Abstractions.Logging;

/// <summary>
/// 提供全局日志工厂访问入口。
/// </summary>
/// <remarks>
/// 该类型位于抽象层,是为了让上层模块可以在不依赖 <c>GFramework.Core</c> 实现程序集的前提下
/// 获取日志记录器。默认 provider 会优先通过反射解析 <c>GFramework.Core</c> 中的控制台实现,
/// 若宿主未加载该程序集,则退回到静默 provider,避免抽象层形成实现层循环依赖。
/// </remarks>
public static class LoggerFactoryResolver
{
private static readonly object ProviderLock = new();

private static string DefaultProviderTypeName =
"GFramework.Core.Logging.ConsoleLoggerFactoryProvider, GFramework.Core";

private static ILoggerFactoryProvider? _provider;

/// <summary>
/// 获取或设置当前日志工厂提供程序。
/// </summary>
/// <remarks>
/// 读取与赋值都会通过同一把锁串行化,确保并发调用方观察到确定的 provider 引用。
/// 当调用方未显式赋值时,会在首次访问时尝试解析默认实现;若解析失败,则退回静默 provider。
/// </remarks>
/// <exception cref="ArgumentNullException">
/// 当赋值为 <see langword="null" /> 时抛出。
/// </exception>
public static ILoggerFactoryProvider Provider
{
get
{
lock (ProviderLock)
{
_provider ??= CreateDefaultProvider();
return _provider;
}
}
set
{
var provider = value ?? throw new ArgumentNullException(nameof(value));

lock (ProviderLock)
{
_provider = provider;
}
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/// <summary>
/// 获取或设置新创建日志记录器的最小日志级别。
/// </summary>
/// <remarks>
/// 该属性直接代理到当前 <see cref="Provider" />,确保调用方调整级别后立即影响后续创建的日志器。
/// </remarks>
public static LogLevel MinLevel
{
get => Provider.MinLevel;
set => Provider.MinLevel = value;
}

private static ILoggerFactoryProvider CreateDefaultProvider()
{
try
{
if (Type.GetType(DefaultProviderTypeName, throwOnError: false) is { } providerType &&
Activator.CreateInstance(providerType) is ILoggerFactoryProvider provider)
{
provider.MinLevel = LogLevel.Info;
return provider;
}
}
catch (Exception)
{
// The default provider is optional. Any load or activation failure must degrade to the silent provider so
// abstractions-only hosts can continue bootstrapping without the concrete logging assembly.
}

return new SilentLoggerFactoryProvider();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

/// <summary>
/// 当宿主未提供默认日志实现时使用的静默 provider。
/// </summary>
private sealed class SilentLoggerFactoryProvider : ILoggerFactoryProvider
{
public LogLevel MinLevel { get; set; } = LogLevel.Info;

public ILogger CreateLogger(string name)
{
return new SilentLogger(name);
}
}

/// <summary>
/// 默认日志实现不可用时的 no-op 日志器。
/// </summary>
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)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Reflection;
using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Architectures;
using GFramework.Core.Logging;
using GFramework.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs;

namespace GFramework.Core.Tests.Architectures;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -714,4 +714,4 @@ public IArchitectureContext GetContext()
return _context;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -185,4 +185,4 @@ public override void Initialize()
private sealed class BootstrapMarker
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
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;

Expand Down Expand Up @@ -460,4 +460,4 @@ public IArchitectureContext GetContext()
return _context;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
3 changes: 2 additions & 1 deletion GFramework.Core.Tests/Architectures/PriorityServiceTests.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -244,4 +245,4 @@ public class PriorityTestUtilityC : IPriorityTestUtility, IPrioritized
public int Priority => 30;
}

#endregion
#endregion
Loading
Loading