refactor(architecture): 重构日志系统和配置属性结构

- 将日志工厂配置改为日志属性配置,使用LoggerProperties替代ILoggerFactory
- 引入ArchitectureProperties替代ArchitectureOptions,统一架构配置属性
- 修改日志记录器创建方式,使用LoggerFactoryResolver.Provider统一管理
- 重构控制台日志工厂提供程序接口,移除minLevel参数
- 更新架构配置接口和上下文接口中的日志相关属性
- 移除Godot日志生成器相关的源代码生成器和特性
- 更新源代码生成器中的日志创建逻辑,使用新的日志工厂解析器
This commit is contained in:
GwWuYou 2026-01-01 21:39:08 +08:00
parent 435c3398fc
commit f620dea073
24 changed files with 114 additions and 242 deletions

View File

@ -1,4 +1,4 @@
using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.properties;
namespace GFramework.Core.Abstractions.architecture; namespace GFramework.Core.Abstractions.architecture;
@ -8,12 +8,12 @@ namespace GFramework.Core.Abstractions.architecture;
public interface IArchitectureConfiguration public interface IArchitectureConfiguration
{ {
/// <summary> /// <summary>
/// 获取或设置日志工厂,用于创建日志记录器实例 /// 获取或设置日志选项,包含日志相关的配置参数
/// </summary> /// </summary>
ILoggerFactory LoggerFactory { get; set; } LoggerProperties LoggerProperties { get; set; }
/// <summary> /// <summary>
/// 获取或设置架构选项,包含架构相关的配置参数 /// 获取或设置架构选项,包含架构相关的配置参数
/// </summary> /// </summary>
ArchitectureOptions Options { get; set; } ArchitectureProperties ArchitectureProperties { get; set; }
} }

View File

@ -1,7 +1,6 @@
using System; using System;
using GFramework.Core.Abstractions.command; using GFramework.Core.Abstractions.command;
using GFramework.Core.Abstractions.events; using GFramework.Core.Abstractions.events;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.model; using GFramework.Core.Abstractions.model;
using GFramework.Core.Abstractions.query; using GFramework.Core.Abstractions.query;
using GFramework.Core.Abstractions.system; using GFramework.Core.Abstractions.system;
@ -14,11 +13,6 @@ namespace GFramework.Core.Abstractions.architecture;
/// </summary> /// </summary>
public interface IArchitectureContext public interface IArchitectureContext
{ {
/// <summary>
/// 获取日志工厂
/// </summary>
ILoggerFactory LoggerFactory { get; }
/// <summary> /// <summary>
/// 获取指定类型的系统实例 /// 获取指定类型的系统实例
/// </summary> /// </summary>

View File

@ -5,11 +5,15 @@
/// </summary> /// </summary>
public interface ILoggerFactoryProvider public interface ILoggerFactoryProvider
{ {
/// <summary>
/// 获取或设置日志记录器的最小日志级别,低于此级别的日志将被忽略
/// </summary>
public LogLevel MinLevel { get; set; }
/// <summary> /// <summary>
/// 创建一个日志记录器实例 /// 创建一个日志记录器实例
/// </summary> /// </summary>
/// <param name="name">日志记录器的名称,用于标识特定的日志源</param> /// <param name="name">日志记录器的名称,用于标识特定的日志源</param>
/// <param name="minLevel">日志记录器的最小日志级别,低于此级别的日志消息将被忽略</param>
/// <returns>配置了指定名称和最小日志级别的ILogger实例</returns> /// <returns>配置了指定名称和最小日志级别的ILogger实例</returns>
ILogger CreateLogger(string name, LogLevel minLevel); ILogger CreateLogger(string name);
} }

View File

@ -1,20 +1,17 @@
namespace GFramework.Core.Abstractions.architecture; namespace GFramework.Core.Abstractions.properties;
/// <summary> /// <summary>
/// 架构选项配置类,用于定义架构行为的相关配置选项 /// 架构选项配置类,用于定义架构行为的相关配置选项
/// </summary> /// </summary>
public sealed class ArchitectureOptions( public sealed class ArchitectureProperties
bool strictPhaseValidation = true,
bool allowLateRegistration = false
)
{ {
/// <summary> /// <summary>
/// 允许延迟注册开关当设置为true时允许在初始化完成后进行组件注册 /// 允许延迟注册开关当设置为true时允许在初始化完成后进行组件注册
/// </summary> /// </summary>
public bool AllowLateRegistration { get; } = allowLateRegistration; public bool AllowLateRegistration { get; set; }
/// <summary> /// <summary>
/// 严格阶段验证开关当设置为true时启用严格的阶段验证机制 /// 严格阶段验证开关当设置为true时启用严格的阶段验证机制
/// </summary> /// </summary>
public bool StrictPhaseValidation { get; } = strictPhaseValidation; public bool StrictPhaseValidation { get; set; }
} }

View File

@ -0,0 +1,15 @@
using GFramework.Core.Abstractions.logging;
namespace GFramework.Core.Abstractions.properties;
/// <summary>
/// 日志配置选项类,用于配置日志系统的相关参数
/// </summary>
public sealed class LoggerProperties
{
/// <summary>
/// 获取或设置日志工厂提供程序
/// 可为空,用于提供自定义的日志工厂实现
/// </summary>
public ILoggerFactoryProvider LoggerFactoryProvider { get; set; } = null!;
}

View File

@ -7,6 +7,7 @@ using GFramework.Core.Abstractions.model;
using GFramework.Core.Abstractions.system; using GFramework.Core.Abstractions.system;
using GFramework.Core.Abstractions.utility; using GFramework.Core.Abstractions.utility;
using GFramework.Core.events; using GFramework.Core.events;
using GFramework.Core.logging;
namespace GFramework.Core.architecture; namespace GFramework.Core.architecture;
@ -70,7 +71,8 @@ public abstract class Architecture(
/// <param name="module">要安装的模块</param> /// <param name="module">要安装的模块</param>
public void InstallModule(IArchitectureModule module) public void InstallModule(IArchitectureModule module)
{ {
var logger = Configuration.LoggerFactory.GetLogger(nameof(Architecture)); var logger =
LoggerFactoryResolver.Provider.CreateLogger(nameof(GetType));
logger.Debug($"Installing module: {module.GetType().Name}"); logger.Debug($"Installing module: {module.GetType().Name}");
RegisterLifecycleHook(module); RegisterLifecycleHook(module);
Container.RegisterPlurality(module); Container.RegisterPlurality(module);
@ -132,28 +134,27 @@ public abstract class Architecture(
/// <exception cref="InvalidOperationException">当阶段转换不被允许时抛出异常</exception> /// <exception cref="InvalidOperationException">当阶段转换不被允许时抛出异常</exception>
private void EnterPhase(ArchitecturePhase next) private void EnterPhase(ArchitecturePhase next)
{ {
var logger = Configuration.LoggerFactory.GetLogger(nameof(Architecture)); if (Configuration.ArchitectureProperties.StrictPhaseValidation &&
if (Configuration.Options.StrictPhaseValidation &&
(!ArchitectureConstants.PhaseTransitions.TryGetValue(CurrentPhase, out var allowed) || (!ArchitectureConstants.PhaseTransitions.TryGetValue(CurrentPhase, out var allowed) ||
!allowed.Contains(next))) !allowed.Contains(next)))
{ {
// 验证阶段转换是否合法 // 验证阶段转换是否合法
var errorMsg = $"Invalid phase transition: {CurrentPhase} -> {next}"; var errorMsg = $"Invalid phase transition: {CurrentPhase} -> {next}";
logger.Fatal(errorMsg); _logger.Fatal(errorMsg);
throw new InvalidOperationException(errorMsg); throw new InvalidOperationException(errorMsg);
} }
var previousPhase = CurrentPhase; var previousPhase = CurrentPhase;
CurrentPhase = next; CurrentPhase = next;
if (previousPhase != next) logger.Info($"Architecture phase changed: {previousPhase} -> {next}"); if (previousPhase != next) _logger.Info($"Architecture phase changed: {previousPhase} -> {next}");
NotifyPhase(next); NotifyPhase(next);
// 通知所有架构阶段感知对象阶段变更 // 通知所有架构阶段感知对象阶段变更
foreach (var obj in Container.GetAll<IArchitecturePhaseAware>()) foreach (var obj in Container.GetAll<IArchitecturePhaseAware>())
{ {
logger.Debug($"Notifying phase-aware object {obj.GetType().Name} of phase change to {next}"); _logger.Debug($"Notifying phase-aware object {obj.GetType().Name} of phase change to {next}");
obj.OnArchitecturePhase(next); obj.OnArchitecturePhase(next);
} }
} }
@ -174,7 +175,7 @@ public abstract class Architecture(
/// <param name="hook">生命周期钩子实例</param> /// <param name="hook">生命周期钩子实例</param>
public void RegisterLifecycleHook(IArchitectureLifecycle hook) public void RegisterLifecycleHook(IArchitectureLifecycle hook)
{ {
if (CurrentPhase >= ArchitecturePhase.Ready && !Configuration.Options.AllowLateRegistration) if (CurrentPhase >= ArchitecturePhase.Ready && !Configuration.ArchitectureProperties.AllowLateRegistration)
throw new InvalidOperationException( throw new InvalidOperationException(
"Cannot register lifecycle hook after architecture is Ready"); "Cannot register lifecycle hook after architecture is Ready");
_lifecycleHooks.Add(hook); _lifecycleHooks.Add(hook);
@ -195,25 +196,23 @@ public abstract class Architecture(
/// </remarks> /// </remarks>
public virtual void Destroy() public virtual void Destroy()
{ {
var logger = Configuration.LoggerFactory.GetLogger(nameof(Architecture));
// 检查当前阶段,如果已经处于销毁或已销毁状态则直接返回 // 检查当前阶段,如果已经处于销毁或已销毁状态则直接返回
if (CurrentPhase >= ArchitecturePhase.Destroying) if (CurrentPhase >= ArchitecturePhase.Destroying)
{ {
logger.Warn("Architecture destroy called but already in destroying/destroyed state"); _logger.Warn("Architecture destroy called but already in destroying/destroyed state");
return; return;
} }
// 进入销毁阶段并发送销毁开始事件 // 进入销毁阶段并发送销毁开始事件
logger.Info("Starting architecture destruction"); _logger.Info("Starting architecture destruction");
EnterPhase(ArchitecturePhase.Destroying); EnterPhase(ArchitecturePhase.Destroying);
TypeEventSystem.Send(new ArchitectureEvents.ArchitectureDestroyingEvent()); TypeEventSystem.Send(new ArchitectureEvents.ArchitectureDestroyingEvent());
// 销毁所有系统组件并清空系统列表 // 销毁所有系统组件并清空系统列表
logger.Info($"Destroying {_allSystems.Count} systems"); _logger.Info($"Destroying {_allSystems.Count} systems");
foreach (var system in _allSystems) foreach (var system in _allSystems)
{ {
logger.Debug($"Destroying system: {system.GetType().Name}"); _logger.Debug($"Destroying system: {system.GetType().Name}");
system.Destroy(); system.Destroy();
} }
@ -222,7 +221,7 @@ public abstract class Architecture(
// 进入已销毁阶段并发送销毁完成事件 // 进入已销毁阶段并发送销毁完成事件
EnterPhase(ArchitecturePhase.Destroyed); EnterPhase(ArchitecturePhase.Destroyed);
TypeEventSystem.Send(new ArchitectureEvents.ArchitectureDestroyedEvent()); TypeEventSystem.Send(new ArchitectureEvents.ArchitectureDestroyedEvent());
logger.Info("Architecture destruction completed"); _logger.Info("Architecture destruction completed");
} }
#endregion #endregion
@ -231,8 +230,10 @@ public abstract class Architecture(
public void Initialize() public void Initialize()
{ {
_logger = Configuration.LoggerFactory.GetLogger(GetType().Name); // 设置日志工厂提供程序,用于创建日志记录器
_context ??= new ArchitectureContext(Container, TypeEventSystem, Configuration.LoggerFactory); LoggerFactoryResolver.Provider = Configuration.LoggerProperties.LoggerFactoryProvider;
_logger = LoggerFactoryResolver.Provider.CreateLogger(GetType().Name);
_context ??= new ArchitectureContext(Container, TypeEventSystem, Configuration.LoggerProperties);
GameContext.Bind(GetType(), _context); GameContext.Bind(GetType(), _context);
// 创建架构运行时实例 // 创建架构运行时实例
Runtime = new ArchitectureRuntime(_context); Runtime = new ArchitectureRuntime(_context);
@ -284,8 +285,11 @@ public abstract class Architecture(
public async Task InitializeAsync() public async Task InitializeAsync()
{ {
_logger = Configuration.LoggerFactory.GetLogger(GetType().Name); // 设置日志工厂提供程序,用于创建日志记录器
_context ??= new ArchitectureContext(Container, TypeEventSystem, Configuration.LoggerFactory); LoggerFactoryResolver.Provider = Configuration.LoggerProperties.LoggerFactoryProvider;
// 创建日志记录器
_logger = LoggerFactoryResolver.Provider.CreateLogger(GetType().Name);
_context ??= new ArchitectureContext(Container, TypeEventSystem, Configuration.LoggerProperties);
GameContext.Bind(GetType(), _context); GameContext.Bind(GetType(), _context);
// 创建架构运行时实例 // 创建架构运行时实例
Runtime = new ArchitectureRuntime(_context); Runtime = new ArchitectureRuntime(_context);
@ -347,7 +351,7 @@ public abstract class Architecture(
/// <param name="system">要注册的系统实例</param> /// <param name="system">要注册的系统实例</param>
public void RegisterSystem<TSystem>(TSystem system) where TSystem : ISystem public void RegisterSystem<TSystem>(TSystem system) where TSystem : ISystem
{ {
if (CurrentPhase >= ArchitecturePhase.Ready && !Configuration.Options.AllowLateRegistration) if (CurrentPhase >= ArchitecturePhase.Ready && !Configuration.ArchitectureProperties.AllowLateRegistration)
{ {
const string errorMsg = "Cannot register system after Architecture is Ready"; const string errorMsg = "Cannot register system after Architecture is Ready";
_logger.Error(errorMsg); _logger.Error(errorMsg);
@ -379,7 +383,7 @@ public abstract class Architecture(
/// <param name="model">要注册的模型实例</param> /// <param name="model">要注册的模型实例</param>
public void RegisterModel<TModel>(TModel model) where TModel : IModel public void RegisterModel<TModel>(TModel model) where TModel : IModel
{ {
if (CurrentPhase >= ArchitecturePhase.Ready && !Configuration.Options.AllowLateRegistration) if (CurrentPhase >= ArchitecturePhase.Ready && !Configuration.ArchitectureProperties.AllowLateRegistration)
{ {
var errorMsg = "Cannot register model after Architecture is Ready"; var errorMsg = "Cannot register model after Architecture is Ready";
_logger.Error(errorMsg); _logger.Error(errorMsg);

View File

@ -1,5 +1,6 @@
using GFramework.Core.Abstractions.architecture; using GFramework.Core.Abstractions.architecture;
using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.properties;
using GFramework.Core.logging; using GFramework.Core.logging;
namespace GFramework.Core.architecture; namespace GFramework.Core.architecture;
@ -8,23 +9,27 @@ namespace GFramework.Core.architecture;
/// 默认架构配置类实现IArchitectureConfiguration接口 /// 默认架构配置类实现IArchitectureConfiguration接口
/// 提供日志工厂、日志级别和架构选项的默认配置 /// 提供日志工厂、日志级别和架构选项的默认配置
/// </summary> /// </summary>
public class ArchitectureConfiguration : IArchitectureConfiguration public sealed class ArchitectureConfiguration : IArchitectureConfiguration
{ {
/// <summary> /// <summary>
/// 获取或设置日志级别 /// 获取或设置日志选项
/// 默认设置为Info级别 /// 默认配置为Info级别日志使用控制台日志工厂提供程序
/// </summary> /// </summary>
public LogLevel LogLevel { get; set; } = LogLevel.Info; public LoggerProperties LoggerProperties { get; set; } = new()
{
/// <summary> LoggerFactoryProvider = new ConsoleLoggerFactoryProvider()
/// 获取或设置日志工厂实例 {
/// 默认使用控制台日志工厂 MinLevel = LogLevel.Info
/// </summary> }
public ILoggerFactory LoggerFactory { get; set; } = new ConsoleLoggerFactory(); };
/// <summary> /// <summary>
/// 获取或设置架构选项 /// 获取或设置架构选项
/// 默认创建新的ArchitectureOptions实例 /// 默认创建新的ArchitectureOptions实例
/// </summary> /// </summary>
public ArchitectureOptions Options { get; set; } = new(); public ArchitectureProperties ArchitectureProperties { get; set; } = new()
{
AllowLateRegistration = false,
StrictPhaseValidation = true
};
} }

View File

@ -2,12 +2,11 @@
using GFramework.Core.Abstractions.command; using GFramework.Core.Abstractions.command;
using GFramework.Core.Abstractions.events; using GFramework.Core.Abstractions.events;
using GFramework.Core.Abstractions.ioc; using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.model; using GFramework.Core.Abstractions.model;
using GFramework.Core.Abstractions.properties;
using GFramework.Core.Abstractions.query; using GFramework.Core.Abstractions.query;
using GFramework.Core.Abstractions.system; using GFramework.Core.Abstractions.system;
using GFramework.Core.Abstractions.utility; using GFramework.Core.Abstractions.utility;
using GFramework.Core.logging;
namespace GFramework.Core.architecture; namespace GFramework.Core.architecture;
@ -17,7 +16,7 @@ namespace GFramework.Core.architecture;
public class ArchitectureContext( public class ArchitectureContext(
IIocContainer container, IIocContainer container,
ITypeEventSystem typeEventSystem, ITypeEventSystem typeEventSystem,
ILoggerFactory? loggerFactory) LoggerProperties loggerProperties)
: IArchitectureContext : IArchitectureContext
{ {
private readonly IIocContainer _container = container ?? throw new ArgumentNullException(nameof(container)); private readonly IIocContainer _container = container ?? throw new ArgumentNullException(nameof(container));
@ -27,8 +26,6 @@ public class ArchitectureContext(
internal IArchitectureRuntime Runtime { get; set; } = null!; internal IArchitectureRuntime Runtime { get; set; } = null!;
public ILoggerFactory LoggerFactory { get; } = loggerFactory ?? new NoopLoggerFactory();
#region Query Execution #region Query Execution
/// <summary> /// <summary>

View File

@ -1,6 +1,7 @@
using GFramework.Core.Abstractions.ioc; using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.system; using GFramework.Core.Abstractions.system;
using GFramework.Core.logging;
using GFramework.Core.rule; using GFramework.Core.rule;
namespace GFramework.Core.ioc; namespace GFramework.Core.ioc;
@ -54,7 +55,8 @@ public class IocContainer : ContextAwareBase, IIocContainer
protected override void OnContextReady() protected override void OnContextReady()
{ {
_logger = Context.LoggerFactory.GetLogger(nameof(IocContainer)); _logger =
LoggerFactoryResolver.Provider.CreateLogger(nameof(GetType));
} }
/// <summary> /// <summary>

View File

@ -7,12 +7,16 @@ namespace GFramework.Core.logging;
/// </summary> /// </summary>
public sealed class ConsoleLoggerFactoryProvider : ILoggerFactoryProvider public sealed class ConsoleLoggerFactoryProvider : ILoggerFactoryProvider
{ {
/// <summary>
/// 获取或设置日志记录器的最小日志级别,低于此级别的日志将被忽略
/// </summary>
public LogLevel MinLevel { get; set; } = LogLevel.Info;
/// <summary> /// <summary>
/// 创建一个日志记录器实例 /// 创建一个日志记录器实例
/// </summary> /// </summary>
/// <param name="name">日志记录器的名称,用于标识特定的日志源</param> /// <param name="name">日志记录器的名称,用于标识特定的日志源</param>
/// <param name="minLevel">日志记录器的最小日志级别,低于此级别的日志消息将被忽略</param>
/// <returns>配置了指定名称和最小日志级别的ILogger实例</returns> /// <returns>配置了指定名称和最小日志级别的ILogger实例</returns>
public ILogger CreateLogger(string name, LogLevel minLevel) public ILogger CreateLogger(string name)
=> new ConsoleLoggerFactory().GetLogger(name, minLevel); => new ConsoleLoggerFactory().GetLogger(name, MinLevel);
} }

View File

@ -15,4 +15,12 @@ public static class LoggerFactoryResolver
/// </value> /// </value>
public static ILoggerFactoryProvider Provider { get; set; } public static ILoggerFactoryProvider Provider { get; set; }
= new ConsoleLoggerFactoryProvider(); = new ConsoleLoggerFactoryProvider();
/// <summary>
/// 获取或设置日志记录的最小级别
/// </summary>
/// <value>
/// 日志级别枚举值默认为Info级别
/// </value>
public static LogLevel MinLevel { get; set; } = LogLevel.Info;
} }

View File

@ -11,7 +11,7 @@ public abstract class ContextAwareBase : IContextAware
/// <summary> /// <summary>
/// 获取当前实例的架构上下文 /// 获取当前实例的架构上下文
/// </summary> /// </summary>
protected IArchitectureContext Context { get; private set; } = null!; protected IArchitectureContext Context { get; set; } = null!;
/// <summary> /// <summary>
/// 设置架构上下文的实现方法,由框架调用 /// 设置架构上下文的实现方法,由框架调用

View File

@ -1,6 +1,7 @@
using GFramework.Core.Abstractions.enums; using GFramework.Core.Abstractions.enums;
using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.system; using GFramework.Core.Abstractions.system;
using GFramework.Core.logging;
using GFramework.Core.rule; using GFramework.Core.rule;
namespace GFramework.Core.system; namespace GFramework.Core.system;
@ -18,7 +19,7 @@ public abstract class AbstractSystem : ContextAwareBase, ISystem
/// </summary> /// </summary>
void ISystem.Init() void ISystem.Init()
{ {
_logger = Context.LoggerFactory.GetLogger(nameof(AbstractSystem)); _logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(GetType));
_logger.Debug($"Initializing system: {GetType().Name}"); _logger.Debug($"Initializing system: {GetType().Name}");
OnInit(); OnInit();

View File

@ -1,5 +1,6 @@
using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.utility; using GFramework.Core.Abstractions.utility;
using GFramework.Core.logging;
using GFramework.Core.rule; using GFramework.Core.rule;
namespace GFramework.Core.utility; namespace GFramework.Core.utility;
@ -18,7 +19,7 @@ public abstract class AbstractContextUtility : ContextAwareBase, IContextUtility
void IContextUtility.Init() void IContextUtility.Init()
{ {
// 获取上下文中的日志记录器 // 获取上下文中的日志记录器
Logger = Context.LoggerFactory.GetLogger(nameof(AbstractContextUtility)); Logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(GetType));
Logger.Debug($"Initializing Context Utility: {GetType().Name}"); Logger.Debug($"Initializing Context Utility: {GetType().Name}");
// 执行子类实现的初始化逻辑 // 执行子类实现的初始化逻辑

View File

@ -15,4 +15,7 @@
<ItemGroup> <ItemGroup>
<Using Include="GFramework.Godot.SourceGenerators.Abstractions"/> <Using Include="GFramework.Godot.SourceGenerators.Abstractions"/>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="logging\"/>
</ItemGroup>
</Project> </Project>

View File

@ -1,38 +0,0 @@
using System;
namespace GFramework.Godot.SourceGenerators.Abstractions.logging;
/// <summary>
/// Godot日志特性用于在类上标记以自动生成日志字段
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class GodotLogAttribute : Attribute
{
/// <summary>
/// 初始化 GodotLogAttribute 类的新实例
/// </summary>
public GodotLogAttribute()
{
}
/// <summary>
/// 初始化 GodotLogAttribute 类的新实例
/// </summary>
/// <param name="name">日志分类名</param>
public GodotLogAttribute(string? name)
{
Name = name;
}
/// <summary>日志分类名(默认使用类名)</summary>
public string? Name { get; set; }
/// <summary>生成字段名</summary>
public string FieldName { get; set; } = "Logger";
/// <summary>是否生成 static 字段</summary>
public bool IsStatic { get; set; } = true;
/// <summary>访问修饰符</summary>
public string AccessModifier { get; set; } = "private";
}

View File

@ -1,3 +0,0 @@
; Shipped analyzer releases
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md

View File

@ -1,8 +0,0 @@
; Unshipped analyzer release
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
### New Rules
Rule ID | Category | Severity | Notes
----------------------|--------------------------|----------|------------------------
GF_Godot_Logging_001 | GFramework.Godot.Logging | Warning | GodotLoggerDiagnostics

View File

@ -59,4 +59,12 @@
<!-- 包含targets文件 --> <!-- 包含targets文件 -->
<None Include="GeWuYou.$(AssemblyName).targets" Pack="true" PackagePath="build" Visible="false"/> <None Include="GeWuYou.$(AssemblyName).targets" Pack="true" PackagePath="build" Visible="false"/>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="diagnostics\"/>
<Folder Include="logging\"/>
</ItemGroup>
<ItemGroup>
<AdditionalFiles Remove="AnalyzerReleases.Shipped.md"/>
<AdditionalFiles Remove="AnalyzerReleases.Unshipped.md"/>
</ItemGroup>
</Project> </Project>

View File

@ -1,25 +0,0 @@
using Microsoft.CodeAnalysis;
namespace GFramework.Godot.SourceGenerators.diagnostics;
/// <summary>
/// 提供诊断描述符的静态类用于GFramework日志生成器的编译时检查
/// </summary>
internal static class GodotLoggerDiagnostics
{
/// <summary>
/// 诊断描述符标识GodotLogAttribute无法在指定类上生成Logger
/// </summary>
/// <remarks>
/// ID: GFW_LOG001
/// 严重性: Warning
/// 分类: GFramework.Godot.Logging
/// </remarks>
public static readonly DiagnosticDescriptor LogAttributeInvalid = new(
"GF_Godot_Logging_001",
"GodotLogAttribute cannot generate Logger",
"GodotLogAttribute on class '{0}' is ineffective: {1}",
"GFramework.Godot.Logging",
DiagnosticSeverity.Warning,
true);
}

View File

@ -1,96 +0,0 @@
using System;
using System.Linq;
using System.Text;
using GFramework.Godot.SourceGenerators.Abstractions.logging;
using GFramework.SourceGenerators.Common.constants;
using GFramework.SourceGenerators.Common.generator;
using Microsoft.CodeAnalysis;
namespace GFramework.Godot.SourceGenerators.logging;
/// <summary>
/// 日志生成器用于为标记了GodotLogAttribute的类自动生成日志字段
/// </summary>
[Generator]
public sealed class GodotLoggerGenerator : TypeAttributeClassGeneratorBase
{
protected override Type AttributeType => typeof(GodotLogAttribute);
protected override string AttributeShortNameWithoutSuffix => "GodotLog";
/// <summary>
/// 生成源代码
/// </summary>
/// <param name="context">源生产上下文</param>
/// <param name="compilation">编译对象</param>
/// <param name="symbol">命名类型符号</param>
/// <param name="attr">属性数据</param>
/// <returns>生成的源代码字符串</returns>
protected override string Generate(
SourceProductionContext context,
Compilation compilation,
INamedTypeSymbol symbol,
AttributeData attr)
{
var ns = symbol.ContainingNamespace.IsGlobalNamespace
? null
: symbol.ContainingNamespace.ToDisplayString();
var className = symbol.Name;
// 解析构造函数参数
var name = className;
if (attr.ConstructorArguments.Length > 0 && attr.ConstructorArguments[0].Value is string s &&
!string.IsNullOrWhiteSpace(s))
{
name = s;
}
// 解析命名参数
var fieldName = GetNamedArg(attr, "FieldName")?.ToString() ?? "_log";
var access = GetNamedArg(attr, "AccessModifier")?.ToString() ?? "private";
var isStatic = GetNamedArg(attr, "IsStatic") is not bool b || b;
var staticKeyword = isStatic ? "static " : "";
var sb = new StringBuilder();
sb.AppendLine("// <auto-generated />");
sb.AppendLine($"using {PathContests.CoreAbstractionsNamespace}.logging;");
sb.AppendLine($"using {PathContests.GodotNamespace}.logging;");
sb.AppendLine();
if (ns is not null)
{
sb.AppendLine($"namespace {ns}");
sb.AppendLine("{");
}
sb.AppendLine($" public partial class {className}");
sb.AppendLine(" {");
sb.AppendLine(" /// <summary>Auto-generated logger</summary>");
sb.AppendLine(
$" {access} {staticKeyword}readonly ILogger {fieldName} = new GodotLoggerFactory().GetLogger(\"{name}\");");
sb.AppendLine(" }");
if (ns is not null)
sb.AppendLine("}");
return sb.ToString();
}
/// <summary>
/// 获取生成文件的提示名称
/// </summary>
/// <param name="symbol">类型符号</param>
/// <returns>生成文件的提示名称</returns>
protected override string GetHintName(INamedTypeSymbol symbol)
=> $"{symbol.Name}.Logger.g.cs";
/// <summary>
/// 获取属性的命名参数值
/// </summary>
/// <param name="attr">属性数据</param>
/// <param name="name">参数名称</param>
/// <returns>参数值</returns>
private static object? GetNamedArg(AttributeData attr, string name)
=> attr.NamedArguments.FirstOrDefault(kv => kv.Key == name).Value.Value;
}

View File

@ -8,11 +8,14 @@ namespace GFramework.Godot.logging;
public sealed class GodotLoggerFactoryProvider : ILoggerFactoryProvider public sealed class GodotLoggerFactoryProvider : ILoggerFactoryProvider
{ {
/// <summary> /// <summary>
/// 创建指定名称和最小日志级别的日志记录器 /// 获取或设置最小日志级别
/// </summary>
public LogLevel MinLevel { get; set; }
/// <summary>
/// 创建指定名称的日志记录器实例
/// </summary> /// </summary>
/// <param name="name">日志记录器的名称</param> /// <param name="name">日志记录器的名称</param>
/// <param name="minLevel">日志记录器的最小日志级别</param> /// <returns>返回配置了最小日志级别的Godot日志记录器实例</returns>
/// <returns>返回配置好的Godot日志记录器实例</returns> public ILogger CreateLogger(string name) => new GodotLoggerFactory().GetLogger(name, MinLevel);
public ILogger CreateLogger(string name, LogLevel minLevel)
=> new GodotLoggerFactory().GetLogger(name, minLevel);
} }

View File

@ -1,6 +1,5 @@
#nullable enable #nullable enable
using System; using System;
using GFramework.Core.Abstractions.logging;
namespace GFramework.SourceGenerators.Abstractions.logging; namespace GFramework.SourceGenerators.Abstractions.logging;
@ -38,7 +37,4 @@ public sealed class LogAttribute : Attribute
/// <summary>访问修饰符</summary> /// <summary>访问修饰符</summary>
public string AccessModifier { get; set; } = "private"; public string AccessModifier { get; set; } = "private";
/// <summary>最小日志级别</summary>
public LogLevel MinLevel { get; set; } = LogLevel.Info;
} }

View File

@ -92,7 +92,7 @@ public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
sb.AppendLine("{"); sb.AppendLine("{");
sb.AppendLine(" /// <summary>Auto-generated logger</summary>"); sb.AppendLine(" /// <summary>Auto-generated logger</summary>");
sb.AppendLine( sb.AppendLine(
$" {access} {staticKeyword}readonly ILogger {fieldName} = new ConsoleLoggerFactory().GetLogger(\"{name}\");"); $" {access} {staticKeyword}readonly ILogger {fieldName} = LoggerFactoryResolver.Provider.CreateLogger(\"{name}\");");
sb.AppendLine("}"); sb.AppendLine("}");
return sb.ToString().TrimEnd(); return sb.ToString().TrimEnd();