mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-23 03:04:29 +08:00
- 创建 GFramework 日志代码生成器完整使用指南 - 包含快速开始示例和基本使用方法说明 - 添加特性参数说明和高级配置示例 - 提供在系统、模型、工具类等不同场景的使用示例 - 整理最佳实践和注意事项部分 - 说明性能考虑和与现有日志系统的兼容性
10 KiB
10 KiB
GFramework 日志代码生成器 (LogAttribute)
概述
GFramework 提供了一个强大的日志代码生成器,类似于 Java 的 @Slf4j 注解。通过在类上使用 [Log] 特性,编译器会自动为该类生成一个日志记录器字段,让您在类的任何地方都能方便地使用日志记录功能。
快速开始
1. 基本使用
在类上添加 [Log] 特性:
using GFramework.Generator.Attributes.generator.logging;
[Log]
public partial class MyService
{
public void DoSomething()
{
// 自动生成的 Log 字段可以直接使用
Log.Info("开始执行操作");
try
{
// 业务逻辑
Log.Debug("执行业务逻辑", new { Operation = "DoSomething" });
Log.Info("操作执行成功");
}
catch (Exception ex)
{
Log.Error("操作执行失败", ex);
}
}
}
编译后,生成器会自动为该类添加:
public partial class MyService
{
private static ILog Log = Log.CreateLogger("MyService");
}
2. 自定义类别名称
[Log("CustomService")]
public partial class MyService
{
// 生成的 logger 类别为 "CustomService" 而不是 "MyService"
}
3. 自定义字段配置
[Log(FieldName = "Logger", AccessModifier = "protected", IsStatic = false)]
public partial class MyService
{
// 生成: protected ILog Logger = Log.CreateLogger("MyService");
}
特性参数说明
LogAttribute 构造函数参数
- category (string, 可选): 指定日志类别,默认为类名
命名参数
- FieldName (string, 默认 "Log"): 指定生成的字段名称
- AccessModifier (string, 默认 "private"): 指定字段的访问修饰符
- IsStatic (bool, 默认 true): 指定字段是否为静态的
使用示例
在系统中的使用
[Log("System")]
public partial class GameSystem : AbstractSystem
{
protected override void OnInit()
{
Log.Info("GameSystem 初始化开始");
// 初始化逻辑
Log.Debug("正在加载游戏数据...");
Log.Info("GameSystem 初始化完成");
}
protected override void OnUpdate(float deltaTime)
{
Log.Trace("系统更新", new { DeltaTime = deltaTime });
}
protected override void OnDestroy()
{
Log.Info("GameSystem 销毁");
}
}
在模型中的使用
[Log("Model")]
public partial class UserModel : AbstractModel
{
public string UserName { get; set; }
public void SetUserName(string userName)
{
Log.Debug("设置用户名", new { OldValue = UserName, NewValue = userName });
UserName = userName;
Log.Info("用户名设置完成", new { UserName = userName });
}
}
在工具类中的使用
[Log("Utility")]
public partial class FileUtility
{
public void SaveFile(string filePath, string content)
{
Log.Debug("开始保存文件", new { FilePath = filePath });
try
{
// 文件保存逻辑
Log.Info("文件保存成功", new { FilePath = filePath });
}
catch (Exception ex)
{
Log.Error("文件保存失败", ex, new { FilePath = filePath });
}
}
}
网络服务中的使用
[Log("Network")]
public partial class NetworkService
{
public async Task<string> GetDataAsync(string url)
{
Log.Debug("发起网络请求", new { Url = url, Method = "GET" });
try
{
var response = await httpClient.GetStringAsync(url);
Log.Info("网络请求成功", new { Url = url, ResponseLength = response.Length });
return response;
}
catch (Exception ex)
{
Log.Error("网络请求失败", ex, new { Url = url });
throw;
}
}
}
数据库服务中的使用
[Log("Database")]
public partial class DatabaseService
{
public async Task<User> GetUserAsync(int userId)
{
Log.Debug("查询用户信息", new { UserId = userId });
try
{
var user = await _dbContext.Users.FindAsync(userId);
if (user != null)
{
Log.Info("用户查询成功", new { UserId = userId, UserName = user.Name });
}
else
{
Log.Warn("用户不存在", new { UserId = userId });
}
return user;
}
catch (Exception ex)
{
Log.Error("用户查询失败", ex, new { UserId = userId });
throw;
}
}
}
高级配置示例
使用静态字段
[Log(IsStatic = true)] // 默认配置
public partial class StaticService
{
public static void StaticMethod()
{
Log.Info("静态方法调用");
}
}
使用实例字段
[Log(IsStatic = false)]
public partial class InstanceService
{
private readonly string _instanceId;
public InstanceService(string instanceId)
{
_instanceId = instanceId;
}
public void InstanceMethod()
{
Log.Info("实例方法调用", new { InstanceId = _instanceId });
}
}
使用受保护的字段
[Log(AccessModifier = "protected")]
public partial class BaseService
{
// 子类可以访问 protected 字段
}
[Log] // 派生类也可以有自己的日志记录器
public partial class DerivedService : BaseService
{
public void DerivedMethod()
{
Log.Info("派生类方法");
// 也可以访问基类的 protected Log 字段
}
}
最佳实践
1. 使用合适的日志类别名称
// 好的做法:使用有意义的类别名称
[Log("UserService")]
public partial class UserService { }
// 避免:使用过于通用的类别名称
[Log("Service")]
public partial class UserService { }
2. 合理设置日志级别
[Log("BusinessLogic")]
public partial class BusinessService
{
public void ProcessOrder(Order order)
{
// 使用 Info 记录重要的业务流程
Log.Info("开始处理订单", new { OrderId = order.Id });
// 使用 Debug 记录调试信息
Log.Debug("订单验证通过", new { OrderId = order.Id });
// 使用 Warning 记录异常情况
if (order.Amount > 10000)
{
Log.Warn("大额订单", new { OrderId = order.Id, Amount = order.Amount });
}
// 使用 Error 记录错误
try
{
// 业务逻辑
}
catch (Exception ex)
{
Log.Error("订单处理失败", ex, new { OrderId = order.Id });
}
}
}
3. 记录上下文信息
[Log("UserManagement")]
public partial class UserManager
{
public void UpdateUserProfile(int userId, UserProfile profile)
{
Log.Info("更新用户资料", new
{
UserId = userId,
Changes = profile.GetChanges(),
Timestamp = DateTime.Now
});
}
}
4. 在异常处理中使用日志
[Log("DataAccess")]
public partial class UserRepository
{
public async Task<User> GetUserAsync(int userId)
{
try
{
return await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
}
catch (DbException ex)
{
Log.Error("数据库查询失败", ex, new { UserId = userId });
throw new DataAccessException("无法获取用户信息", ex);
}
}
}
框架组件集成
在 GFramework 架构中使用
[Log("Architecture")]
public partial class ExampleArchitecture : AbstractArchitecture
{
protected override void Init()
{
Log.Info("ExampleArchitecture 初始化开始");
// 注册系统
RegisterSystem(new GameSystem());
RegisterSystem(new UISystem());
// 注册模型
RegisterModel(new UserModel());
RegisterModel(new GameModel());
// 注册工具
RegisterUtility(new FileUtility());
Log.Info("ExampleArchitecture 初始化完成");
}
}
在事件处理中使用
[Log("Event")]
public partial class UserEventHandler
{
[Log("EventHandler")]
public void OnUserLoginEvent(UserLoginEvent evt)
{
Log.Info("用户登录事件", new
{
UserId = evt.UserId,
LoginTime = evt.LoginTime,
IpAddress = evt.IpAddress
});
}
[Log("EventHandler")]
public void OnUserLogoutEvent(UserLogoutEvent evt)
{
Log.Info("用户登出事件", new
{
UserId = evt.UserId,
LogoutTime = evt.LogoutTime,
SessionDuration = evt.SessionDuration
});
}
}
注意事项
-
部分类: 使用
[Log]特性的类必须是partial类,因为生成器会添加字段到同一个类中。 -
命名空间引用: 确保项目中引用了
GFramework.Generator.Attributes包。 -
编译时生成: 日志字段是在编译时生成的,不会影响运行时性能。
-
多线程安全: 生成的
ILog实例是线程安全的,可以在多线程环境中使用。 -
继承: 派生类可以有自己的
[Log]特性,也可以访问基类的受保护日志字段。
性能考虑
- 编译时生成: 字段在编译时生成,没有运行时开销
- 延迟初始化: 日志记录器按需创建,避免不必要的对象创建
- 级别检查: 生成的代码包含级别检查,性能与手动创建的日志记录器相同
与现有日志系统的兼容性
生成的代码完全兼容现有的 GFramework.Core.logging 系统:
// 现有的方式仍然可以使用
var manualLogger = Log.CreateLogger("Manual");
// 新生成的字段也可以正常使用
[Log]
public partial class MyService
{
public void Method()
{
// 两种方式都可以使用
manualLogger.Info("手动创建的日志");
Log.Info("自动生成的日志");
}
}
通过使用 [Log] 特性,您可以显著减少样板代码,提高开发效率,同时保持日志记录的一致性和灵活性。