mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
- 将架构相关接口从 GFramework.Core 迁移至 GFramework.Core.Abstractions 项目 - 更新项目引用配置,添加对抽象层项目的项目引用 - 修正命名空间引用,使用新的抽象层命名空间 - 调整类型定义,将 List<T> 替换为更通用的 IList<T> 接口 - 修复控制器接口命名空间错误 - 添加必要的 using 语句以支持新的抽象层引用
Extensions 包使用说明
概述
Extensions 包提供了一系列扩展方法,简化了框架各个接口的使用。通过扩展方法,可以用更简洁的语法访问框架功能,提高代码可读性和开发效率。
扩展方法类别
1. 获取组件扩展 (CanGetExtensions.cs)
为 ICanGetModel、ICanGetSystem、
ICanGetUtility 提供扩展方法。
CanGetModelExtension
public static T GetModel<T>(this ICanGetModel self) where T : class, IModel
使用示例:
// 在 Controller、Command、Query 中使用
public class PlayerController : IController
{
public void UpdateUI()
{
// 直接通过 this 调用
var playerModel = this.GetModel<PlayerModel>();
var inventoryModel = this.GetModel<InventoryModel>();
}
}
CanGetSystemExtension
public static T GetSystem<T>(this ICanGetSystem self) where T : class, ISystem
使用示例:
public class SaveCommand : AbstractCommand
{
protected override void OnExecute()
{
// 获取系统
var saveSystem = this.GetSystem<SaveSystem>();
var networkSystem = this.GetSystem<NetworkSystem>();
saveSystem.SaveGame();
}
}
CanGetUtilityExtension
public static T GetUtility<T>(this ICanGetUtility self) where T : class, IUtility
使用示例:
public class GameModel : AbstractModel
{
protected override void OnInit()
{
// 获取工具
var timeUtility = this.GetUtility<TimeUtility>();
var storageUtility = this.GetUtility<StorageUtility>();
}
}
2. 发送命令扩展 (CanSendExtensions.cs)
为 ICanSendCommand 提供扩展方法。
CanSendCommandExtension
// 发送无参命令(通过类型)
public static void SendCommand<T>(this ICanSendCommand self)
where T : ICommand, new()
// 发送命令实例
public static void SendCommand<T>(this ICanSendCommand self, T command)
where T : ICommand
// 发送带返回值的命令
public static TResult SendCommand<TResult>(this ICanSendCommand self,
ICommand<TResult> command)
使用示例:
public class GameController : IController
{
public void OnStartButtonClicked()
{
// 方式1:通过类型发送(需要无参构造函数)
this.SendCommand<StartGameCommand>();
// 方式2:发送命令实例
this.SendCommand(new LoadLevelCommand(levelId: 1));
// 方式3:发送带返回值的命令
var score = this.SendCommand(new CalculateScoreCommand());
}
}
3. 发送事件扩展 (CanSendExtensions.cs)
为 ICanSendEvent 提供扩展方法。
CanSendEventExtension
// 发送无参事件
public static void SendEvent<T>(this ICanSendEvent self) where T : new()
// 发送事件实例
public static void SendEvent<T>(this ICanSendEvent self, T e)
使用示例:
public class PlayerModel : AbstractModel
{
public void TakeDamage(int damage)
{
Health -= damage;
if (Health <= 0)
{
// 方式1:发送无参事件
this.SendEvent<PlayerDiedEvent>();
// 方式2:发送带数据的事件
this.SendEvent(new PlayerDiedEvent
{
Position = Position,
Cause = "Damage"
});
}
}
}
4. 发送查询扩展 (CanSendExtensions.cs)
为 ICanSendQuery 提供扩展方法。
CanSendQueryExtension
public static TResult SendQuery<TResult>(this ICanSendQuery self,
IQuery<TResult> query)
使用示例:
public class InventoryController : IController
{
public void ShowInventory()
{
// 发送查询获取数据
var items = this.SendQuery(new GetInventoryItemsQuery());
var gold = this.SendQuery(new GetPlayerGoldQuery());
UpdateInventoryUI(items, gold);
}
}
5. 注册事件扩展 (CanRegisterEventExtensions.cs)
为 ICanRegisterEvent 提供扩展方法。
CanRegisterEventExtensions
// 注册事件
public static IUnRegister RegisterEvent<T>(this ICanRegisterEvent self,
Action<T> onEvent)
// 注销事件
public static void UnRegisterEvent<T>(this ICanRegisterEvent self,
Action<T> onEvent)
使用示例:
public class GameController : Node, IController
{
private IUnRegisterList _unregisterList = new UnRegisterList();
public override void _Ready()
{
// 注册事件监听
this.RegisterEvent<GameStartedEvent>(OnGameStarted)
.AddToUnregisterList(_unregisterList);
this.RegisterEvent<PlayerLevelUpEvent>(OnPlayerLevelUp)
.AddToUnregisterList(_unregisterList);
}
private void OnGameStarted(GameStartedEvent e) { }
private void OnPlayerLevelUp(PlayerLevelUpEvent e) { }
}
6. OrEvent 扩展 (OrEventExtensions.cs)
为 IEasyEvent 提供事件组合功能。
OrEventExtensions
public static OrEvent Or(this IEasyEvent self, IEasyEvent e)
使用示例:
// 组合多个事件:当任意一个触发时执行
var onAnyInput = onKeyPressed.Or(onMouseClicked).Or(onTouchDetected);
onAnyInput.Register(() =>
{
GD.Print("Any input detected!");
});
// 链式组合
var onAnyDamage = onPhysicalDamage
.Or(onMagicDamage)
.Or(onPoisonDamage);
7. UnRegister 扩展 (UnRegisterExtension.cs)
为 IUnRegister 提供 Godot 生命周期绑定。
UnRegisterExtension
public static IUnRegister UnRegisterWhenNodeExitTree(this IUnRegister unRegister,
Node node)
使用示例:
#if GODOT
public class PlayerController : Node, IController
{
public override void _Ready()
{
// 当节点退出场景树时自动注销
this.RegisterEvent<GameEvent>(OnGameEvent)
.UnRegisterWhenNodeExitTree(this);
this.GetModel<PlayerModel>()
.Health
.Register(OnHealthChanged)
.UnRegisterWhenNodeExitTree(this);
}
// 不需要手动在 _ExitTree 中注销
}
#endif
8. UnRegisterList 扩展 (UnRegisterListExtension.cs)
为 IUnRegister 和 IUnRegisterList 提供批量管理功能。
UnRegisterListExtension
// 添加到注销列表
public static void AddToUnregisterList(this IUnRegister self,
IUnRegisterList unRegisterList)
// 批量注销
public static void UnRegisterAll(this IUnRegisterList self)
使用示例:
public class ComplexController : Node, IController
{
private IUnRegisterList _unregisterList = new UnRegisterList();
public override void _Ready()
{
// 所有注册都添加到列表中
this.RegisterEvent<Event1>(OnEvent1)
.AddToUnregisterList(_unregisterList);
this.RegisterEvent<Event2>(OnEvent2)
.AddToUnregisterList(_unregisterList);
this.GetModel<Model1>().Property1.Register(OnProperty1Changed)
.AddToUnregisterList(_unregisterList);
this.GetModel<Model2>().Property2.Register(OnProperty2Changed)
.AddToUnregisterList(_unregisterList);
}
public override void _ExitTree()
{
// 一次性注销所有
_unregisterList.UnRegisterAll();
}
}
完整使用示例
Controller 示例
public partial class GameplayController : Node, IController
{
private IUnRegisterList _unregisterList = new UnRegisterList();
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public override void _Ready()
{
// 使用扩展方法获取 Model
var playerModel = this.GetModel<PlayerModel>();
var gameModel = this.GetModel<GameModel>();
// 使用扩展方法注册事件
this.RegisterEvent<GameStartedEvent>(OnGameStarted)
.AddToUnregisterList(_unregisterList);
// 监听可绑定属性
playerModel.Health.Register(OnHealthChanged)
.AddToUnregisterList(_unregisterList);
// 或者使用 Godot 特定的自动注销
gameModel.Score.Register(OnScoreChanged)
.UnRegisterWhenNodeExitTree(this);
}
public override void _Process(double delta)
{
if (Input.IsActionJustPressed("attack"))
{
// 使用扩展方法发送命令
this.SendCommand(new AttackCommand(targetId: 1));
}
if (Input.IsActionJustPressed("use_item"))
{
// 使用扩展方法发送查询
var hasPotion = this.SendQuery(new HasItemQuery("health_potion"));
if (hasPotion)
{
this.SendCommand<UseHealthPotionCommand>();
}
}
}
private void OnGameStarted(GameStartedEvent e)
{
GD.Print("Game started!");
}
private void OnHealthChanged(int health)
{
UpdateHealthBar(health);
}
private void OnScoreChanged(int score)
{
UpdateScoreDisplay(score);
}
public override void _ExitTree()
{
_unregisterList.UnRegisterAll();
}
}
Command 示例
public class ComplexGameCommand : AbstractCommand
{
protected override void OnExecute()
{
// 获取多个组件
var playerModel = this.GetModel<PlayerModel>();
var gameSystem = this.GetSystem<GameSystem>();
var timeUtility = this.GetUtility<TimeUtility>();
// 执行业务逻辑
var currentTime = timeUtility.GetCurrentTime();
gameSystem.ProcessGameLogic(playerModel, currentTime);
// 发送事件通知
this.SendEvent(new GameStateChangedEvent());
// 可以发送其他命令(谨慎使用)
this.SendCommand<SaveGameCommand>();
}
}
System 示例
public class AchievementSystem : AbstractSystem
{
protected override void OnInit()
{
// 注册事件监听
this.RegisterEvent<EnemyKilledEvent>(OnEnemyKilled);
this.RegisterEvent<LevelCompletedEvent>(OnLevelCompleted);
}
private void OnEnemyKilled(EnemyKilledEvent e)
{
// 获取模型
var playerModel = this.GetModel<PlayerModel>();
playerModel.EnemyKillCount++;
// 检查成就
if (playerModel.EnemyKillCount >= 100)
{
// 发送成就解锁事件
this.SendEvent(new AchievementUnlockedEvent
{
AchievementId = "kill_100_enemies"
});
}
}
private void OnLevelCompleted(LevelCompletedEvent e)
{
// 发送查询
var completionTime = this.SendQuery(new GetLevelTimeQuery(e.LevelId));
if (completionTime < 60)
{
this.SendEvent(new AchievementUnlockedEvent
{
AchievementId = "speed_runner"
});
}
}
}
扩展方法的优势
- 简洁的语法:不需要显式调用
GetArchitecture() - 类型安全:编译时检查类型
- 可读性高:代码意图更清晰
- 智能提示:IDE 可以提供完整的自动补全
- 链式调用:支持流式编程风格
注意事项
-
确保引用命名空间:
using GFramework.framework.extensions; -
理解扩展方法本质:
- 扩展方法是静态方法的语法糖
- 不会改变原始类型的结构
- 仅在编译时解析
-
Godot 特定功能:
UnRegisterWhenNodeExitTree仅在 Godot 环境下可用- 使用
#if GODOT编译指令控制
-
性能考虑:
- 扩展方法本身无性能开销
- 实际调用的是底层方法