GFramework/docs/zh-CN/source-generators/logging-generator.md
GeWuYou 1b9e81bbdb refactor(docs): 将控制器实现转换为上下文感知模式
- 将 IController 实现改为使用 [ContextAware] 特性和 partial 类
- 移除手动实现的 GetArchitecture 方法
- 将架构交互方法从 this 调用改为 Context 调用
- 添加必要的 using 语句以支持新的架构访问方式
- 更新所有涉及模型、系统、工具和事件的架构访问代码
- 统一架构访问模式以提高代码一致性和可维护性
2026-03-08 11:03:02 +08:00

342 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 日志生成器
> GFramework.SourceGenerators 自动生成日志代码,减少样板代码
## 概述
日志生成器是一个 Source Generator它会自动为标记了 `[Log]` 特性的类生成 ILogger 字段。这消除了手动编写日志字段的需要,让开发者专注于业务逻辑。
## 基本用法
### 标记类
```csharp
using GFramework.SourceGenerators.Abstractions.logging;
[Log]
public partial class MyService
{
public void DoSomething()
{
// 自动生成的 Logger 字段可直接使用
Logger.Info("执行操作");
}
}
```
### 生成代码
上面的代码会被编译时转换为:
```csharp
// <auto-generated/>
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
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.logging;
using GFramework.SourceGenerators.Abstractions.rule;
[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)