# 日志生成器 > GFramework.SourceGenerators 自动生成日志代码,减少样板代码 ## 概述 日志生成器是一个 Source Generator,它会自动为标记了 `[Log]` 特性的类生成 ILogger 字段。这消除了手动编写日志字段的需要,让开发者专注于业务逻辑。 ## 基本用法 ### 标记类 ```csharp using GFramework.SourceGenerators.Abstractions.logging; [Log] public partial class MyService { public void DoSomething() { // 自动生成的 Logger 字段可直接使用 Logger.Info("执行操作"); } } ``` ### 生成代码 上面的代码会被编译时转换为: ```csharp // public partial class MyService { private static readonly ILogger Logger = LoggerFactoryResolver.Provider.CreateLogger("YourNamespace.MyService"); } ``` **注意**:生成器只生成 ILogger 字段,不生成日志方法。日志方法(Info、Debug、Error 等)来自 ILogger 接口本身。 ## 日志级别 生成的 Logger 字段支持 ILogger 接口的所有方法: ```csharp [Log] public partial class MyClass { public void Example() { // 调试信息 Logger.Debug($"调试信息: {value}"); // 普通信息 Logger.Info("操作成功"); // 警告 Logger.Warning($"警告: {message}"); // 错误 Logger.Error($"错误: {ex.Message}"); // 严重错误 Logger.Critical("系统故障"); } } ``` ## 自定义日志类别 ```csharp [Log("Gameplay")] public partial class GameplaySystem { // 日志会标记为 Gameplay 类别 public void Update() { Logger.Info("游戏逻辑更新"); } } ``` ## 配置选项 ### 自定义字段名称 ```csharp [Log(FieldName = "_customLogger")] public partial class MyClass { public void DoSomething() { // 使用自定义字段名 _customLogger.Info("使用自定义日志器"); } } ``` ### 非静态字段 ```csharp [Log(IsStatic = false)] public partial class InstanceLogger { // 生成实例字段而非静态字段 public void LogMessage() { Logger.Info("实例日志"); } } ``` ### 访问修饰符 ```csharp [Log(AccessModifier = "protected")] public partial class ProtectedLogger { // 生成 protected 字段 } ``` ### 配置选项说明 | 参数 | 类型 | 默认值 | 说明 | |----------------|---------|-----------|---------------------------------| | Name | string? | null | 日志分类名称(默认使用类名) | | FieldName | string | "Logger" | 生成的字段名称 | | IsStatic | bool | true | 是否生成静态字段 | | AccessModifier | string | "private" | 访问修饰符(private/protected/public) | ## 与其他模块集成 ### 与 Godot 集成 ```csharp [Log] [ContextAware] public partial class GodotController : Node { public override void _Ready() { Logger.Info("控制器已准备就绪"); } } ``` ### 与架构集成 ```csharp [Log] public partial class MySystem : AbstractSystem { protected override void OnInit() { Logger.Info("系统初始化"); } } ``` ## 实际应用示例 ### 游戏控制器 ```csharp [Log] [ContextAware] public partial class PlayerController : IController { public void HandleInput(string action) { Logger.Debug($"处理输入: {action}"); switch (action) { case "jump": Logger.Info("玩家跳跃"); Jump(); break; case "attack": Logger.Info("玩家攻击"); Attack(); break; default: Logger.Warning($"未知操作: {action}"); break; } } private void Jump() { try { // 跳跃逻辑 Logger.Debug("跳跃执行成功"); } catch (Exception ex) { Logger.Error($"跳跃失败: {ex.Message}"); } } } ``` ### 数据处理服务 ```csharp [Log("DataService")] public partial class DataProcessor { public void ProcessData(string data) { Logger.Info($"开始处理数据,长度: {data.Length}"); if (string.IsNullOrEmpty(data)) { Logger.Warning("数据为空,跳过处理"); return; } try { // 处理逻辑 Logger.Debug("数据处理中..."); // ... Logger.Info("数据处理完成"); } catch (Exception ex) { Logger.Error($"数据处理失败: {ex.Message}"); throw; } } } ``` ## 最佳实践 ### 1. 合理使用日志级别 ```csharp [Log] public partial class BestPracticeExample { public void ProcessRequest() { // Debug: 详细的调试信息 Logger.Debug("开始处理请求"); // Info: 重要的业务流程信息 Logger.Info("请求处理成功"); // Warning: 可恢复的异常情况 Logger.Warning("缓存未命中,使用默认值"); // Error: 错误但不影响系统运行 Logger.Error("处理失败,将重试"); // Critical: 严重错误,可能导致系统崩溃 Logger.Critical("数据库连接失败"); } } ``` ### 2. 避免过度日志 ```csharp [Log] public partial class PerformanceExample { private int _frameCount = 0; public void Update() { // 好的做法:定期记录 if (_frameCount % 1000 == 0) { Logger.Debug($"已运行 {_frameCount} 帧"); } _frameCount++; // 避免:每帧都记录 // Logger.Debug($"帧 {_frameCount}"); // ❌ 太频繁 } } ``` ### 3. 结构化日志信息 ```csharp [Log] public partial class StructuredLogging { public void ProcessUser(int userId, string action) { // 好的做法:包含上下文信息 Logger.Info($"用户操作 [UserId={userId}, Action={action}]"); // 避免:信息不完整 // Logger.Info("用户操作"); // ❌ 缺少上下文 } } ``` ## 常见问题 ### Q: 为什么需要 partial 关键字? **A**: 源代码生成器需要向现有类添加代码,`partial` 关键字允许一个类的定义分散在多个文件中。 ### Q: 可以在静态类中使用吗? **A**: 可以,生成器会自动生成静态字段: ```csharp [Log] public static partial class StaticHelper { public static void DoSomething() { Logger.Info("静态方法日志"); } } ``` ### Q: 如何自定义日志工厂? **A**: 通过配置 `LoggerFactoryResolver.Provider` 来自定义日志工厂实现。 --- **相关文档**: - [Source Generators 概述](./index) - [枚举扩展生成器](./enum-generator) - [ContextAware 生成器](./context-aware-generator)