refactor(docs): 将控制器实现转换为上下文感知模式

- 将 IController 实现改为使用 [ContextAware] 特性和 partial 类
- 移除手动实现的 GetArchitecture 方法
- 将架构交互方法从 this 调用改为 Context 调用
- 添加必要的 using 语句以支持新的架构访问方式
- 更新所有涉及模型、系统、工具和事件的架构访问代码
- 统一架构访问模式以提高代码一致性和可维护性
This commit is contained in:
GeWuYou 2026-03-08 11:03:02 +08:00
parent 5190b7a463
commit 1b9e81bbdb
26 changed files with 18344 additions and 18165 deletions

View File

@ -1,10 +1,38 @@
namespace GFramework.Core.Abstractions.controller;
/// <summary>
/// 控制器接口,定义了控制器的基本契约和行为规范
/// 控制器标记接口,用于标识控制器组件
/// </summary>
/// <remarks>
/// 该接口为框架中的控制器组件提供统一的抽象定义,
/// 用于实现控制器的标准功能和生命周期管理
/// <para>
/// IController 是一个标记接口Marker Interface不包含任何方法或属性。
/// 它的作用是标识一个类是控制器,用于协调 Model、System 和 UI 之间的交互。
/// </para>
/// <para>
/// <strong>架构访问</strong>:控制器通常需要访问架构上下文。使用 [ContextAware] 特性
/// 自动生成上下文访问能力:
/// </para>
/// <code>
/// using GFramework.SourceGenerators.Abstractions.rule;
///
/// [ContextAware]
/// public partial class PlayerController : IController
/// {
/// public void Initialize()
/// {
/// // Context 属性由 [ContextAware] 自动生成
/// var playerModel = Context.GetModel&lt;PlayerModel&gt;();
/// var gameSystem = Context.GetSystem&lt;GameSystem&gt;();
/// }
/// }
/// </code>
/// <para>
/// <strong>注意</strong>
/// </para>
/// <list type="bullet">
/// <item>必须添加 partial 关键字</item>
/// <item>[ContextAware] 特性会自动实现 IContextAware 接口</item>
/// <item>Context 属性提供架构上下文访问</item>
/// </list>
/// </remarks>
public interface IController;

View File

@ -319,10 +319,9 @@ public class BuyItemCommand : AbstractCommand&lt;BuyItemInput&gt;
}
// 使用命令
public class ShopController : IController
[ContextAware]
public partial class ShopController : IController
{
public IArchitecture GetArchitecture() =&gt; GameArchitecture.Interface;
public void OnBuyButtonClicked(string itemId, int quantity)
{
// 创建并发送命令
@ -332,7 +331,7 @@ public class ShopController : IController
Quantity = quantity
};
this.SendCommand(new BuyItemCommand { Input = input });
Context.SendCommand(new BuyItemCommand { Input = input });
}
}
```
@ -456,15 +455,14 @@ public class GetPlayerStatsQuery : AbstractQuery&lt;GetPlayerStatsInput, PlayerS
}
// 使用查询
public class CharacterPanelController : IController
[ContextAware]
public partial class CharacterPanelController : IController
{
public IArchitecture GetArchitecture() =&gt; GameArchitecture.Interface;
public void ShowCharacterStats()
{
var input = new GetPlayerStatsInput { PlayerId = "player1" };
var query = new GetPlayerStatsQuery { Input = input };
var stats = this.SendQuery(query);
var stats = Context.SendQuery(query);
// 显示统计信息
DisplayStats(stats);
@ -623,20 +621,19 @@ public class AchievementSystem : AbstractSystem
}
// Controller 监听事件
public class UIController : IController
[ContextAware]
public partial class UIController : IController
{
private IUnRegisterList _unregisterList = new UnRegisterList();
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void Initialize()
{
// 监听成就解锁事件
this.RegisterEvent&lt;AchievementUnlockedEvent&gt;(OnAchievementUnlocked)
Context.RegisterEvent<AchievementUnlockedEvent>(OnAchievementUnlocked)
.AddToUnregisterList(_unregisterList);
// 监听玩家死亡事件
this.RegisterEvent&lt;PlayerDiedEvent&gt;(OnPlayerDied)
Context.RegisterEvent<PlayerDiedEvent>(OnPlayerDied)
.AddToUnregisterList(_unregisterList);
}
@ -660,8 +657,11 @@ public class UIController : IController
### 事件组合
```csharp
using GFramework.SourceGenerators.Abstractions.rule;
// 使用 OrEvent 组合多个事件
public class InputController : IController
[ContextAware]
public partial class InputController : IController
{
public void Initialize()
{
@ -877,18 +877,17 @@ public class GameplaySystem : AbstractSystem
}
// 在 Controller 中使用
public class MenuController : IController
[ContextAware]
public partial class MenuController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void OnStartButtonClicked()
{
// 通过架构获取服务
var gameModel = this.GetModel&lt;GameModel&gt;();
var gameModel = Context.GetModel<GameModel>();
gameModel.GameState.Value = GameState.Playing;
// 发送命令
this.SendCommand(new StartGameCommand());
Context.SendCommand(new StartGameCommand());
}
}
```
@ -1259,26 +1258,25 @@ public class GameArchitecture : Architecture
}
// 使用状态机
public class GameController : IController
[ContextAware]
public partial class GameController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public async Task StartGame()
{
var stateMachine = this.GetSystem&lt;IStateMachineSystem&gt;();
await stateMachine.ChangeToAsync&lt;GameplayState&gt;();
var stateMachine = Context.GetSystem<IStateMachineSystem>();
await stateMachine.ChangeToAsync<GameplayState>();
}
public async Task PauseGame()
{
var stateMachine = this.GetSystem&lt;IStateMachineSystem&gt;();
await stateMachine.ChangeToAsync&lt;PauseState&gt;();
var stateMachine = Context.GetSystem<IStateMachineSystem>();
await stateMachine.ChangeToAsync<PauseState>();
}
public async Task ResumeGame()
{
var stateMachine = this.GetSystem&lt;IStateMachineSystem&gt;();
await stateMachine.ChangeToAsync&lt;GameplayState&gt;();
var stateMachine = Context.GetSystem<IStateMachineSystem>();
await stateMachine.ChangeToAsync<GameplayState>();
}
}
```

View File

@ -32,12 +32,16 @@ public class CombatSystem : AbstractSystem
}
}
public class PlayerController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PlayerController : IController
{
// Controller连接 UI 和逻辑
public void Initialize()
{
var player = _architecture.GetModel<PlayerModel>();
var player = Context.GetModel<PlayerModel>();
player.Health.RegisterWithInitValue(OnHealthChanged);
}
@ -177,16 +181,20 @@ public class StorageUtility : IUtility { }
### 1. 正确的注销管理
```csharp
public class MyController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class MyController : IController
{
private IUnRegisterList _unregisterList = new UnRegisterList();
public void Initialize()
{
var model = _architecture.GetModel<PlayerModel>();
var model = Context.GetModel<PlayerModel>();
// 注册事件并添加到注销列表
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied)
Context.RegisterEvent<PlayerDiedEvent>(OnPlayerDied)
.AddToUnregisterList(_unregisterList);
// 注册属性监听并添加到注销列表
@ -235,7 +243,7 @@ public class GameManager
// ❌ 低效:每次都查询
public void Update()
{
var model = _architecture.GetModel<PlayerModel>();
var model = Context.GetModel<PlayerModel>();
model.Health.Value -= 1;
}
@ -244,7 +252,7 @@ private PlayerModel _playerModel;
public void Initialize()
{
_playerModel = _architecture.GetModel<PlayerModel>();
_playerModel = Context.GetModel<PlayerModel>();
}
public void Update()
@ -259,7 +267,7 @@ public void Update()
// ❌ 低效:每帧创建新事件
public void Update()
{
this.SendEvent(new UpdateEvent()); // 频繁分配内存
Context.SendEvent(new UpdateEvent()); // 频繁分配内存
}
// ✅ 高效:复用事件或使用对象池
@ -267,7 +275,7 @@ private UpdateEvent _updateEvent = new UpdateEvent();
public void Update()
{
this.SendEvent(_updateEvent);
Context.SendEvent(_updateEvent);
}
```
@ -437,7 +445,7 @@ public class CombatSystem : AbstractSystem
// ❌ 错误:可能导致内存泄漏
public void Initialize()
{
this.RegisterEvent<Event1>(OnEvent1); // 未注销
Context.RegisterEvent<Event1>(OnEvent1); // 未注销
}
// ✅ 正确
@ -445,7 +453,7 @@ private IUnRegisterList _unregisterList = new UnRegisterList();
public void Initialize()
{
this.RegisterEvent<Event1>(OnEvent1)
Context.RegisterEvent<Event1>(OnEvent1)
.AddToUnregisterList(_unregisterList);
}

View File

@ -277,18 +277,22 @@ public class PoolMonitorSystem : AbstractSystem
### 1. 避免事件订阅泄漏
```csharp
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
// ✅ 好的做法:正确管理事件订阅
public class PlayerController : Node, IController
[ContextAware]
public partial class PlayerController : Node, IController
{
private IUnRegisterList _unRegisterList = new UnRegisterList();
private PlayerModel _playerModel;
public void Initialize(IArchitectureContext context)
public void Initialize()
{
_playerModel = context.GetModel&lt;PlayerModel&gt;();
_playerModel = Context.GetModel&lt;PlayerModel&gt;();
// 使用 UnRegisterList 管理订阅
context.RegisterEvent&lt;PlayerDamagedEvent&gt;(OnPlayerDamaged)
Context.RegisterEvent&lt;PlayerDamagedEvent&gt;(OnPlayerDamaged)
.AddTo(_unRegisterList);
_playerModel.Health.Register(OnHealthChanged)
@ -306,14 +310,15 @@ public class PlayerController : Node, IController
}
// ❌ 避免:忘记取消订阅
public class PlayerController : Node, IController
[ContextAware]
public partial class PlayerController : Node, IController
{
public void Initialize(IArchitectureContext context)
public void Initialize()
{
// 订阅事件但从不取消订阅
context.RegisterEvent&lt;PlayerDamagedEvent&gt;(OnPlayerDamaged);
Context.RegisterEvent&lt;PlayerDamagedEvent&gt;(OnPlayerDamaged);
var playerModel = context.GetModel&lt;PlayerModel&gt;();
var playerModel = Context.GetModel&lt;PlayerModel&gt;();
playerModel.Health.Register(OnHealthChanged);
// 当对象被销毁时,这些订阅仍然存在,导致内存泄漏

View File

@ -176,23 +176,25 @@ await architecture.WaitUntilReadyAsync();
// 4. 通过依赖注入使用架构
// 在 Controller 或其他组件中获取架构实例
public class GameController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
public void Start()
{
// 获取 Model
var playerModel = this.GetModel<PlayerModel>();
// 获取 Model(通过 Context 属性访问架构)
var playerModel = Context.GetModel<PlayerModel>();
// 发送命令
this.SendCommand(new StartGameCommand());
Context.SendCommand(new StartGameCommand());
// 发送查询
var score = this.SendQuery(new GetScoreQuery());
var score = Context.SendQuery(new GetScoreQuery());
// 注册事件
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
Context.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
}
private void OnPlayerDied(PlayerDiedEvent e)

View File

@ -56,13 +56,15 @@ public class SimpleCommand : AbstractCommand
}
// 使用命令
public class GameController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
public void OnRestoreHealthButtonClicked()
{
this.SendCommand(new SimpleCommand());
Context.SendCommand(new SimpleCommand());
}
}
```
@ -194,14 +196,16 @@ public class StartGameCommand : AbstractCommand<StartGameInput>
}
// 使用命令
public class GameController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
public void OnStartButtonClicked()
{
var input = new StartGameInput { LevelId = 1, PlayerName = "Player1" };
this.SendCommand(new StartGameCommand { Input = input });
Context.SendCommand(new StartGameCommand { Input = input });
}
}
```

View File

@ -622,13 +622,14 @@ public class SettingsSystem : AbstractSystem
### 在 Controller 中使用
```csharp
public class SettingsController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class SettingsController : IController
{
public void ApplyGraphicsSettings(int quality, bool fullscreen)
{
var config = this.GetUtility<IConfigurationManager>();
var config = Context.GetUtility<IConfigurationManager>();
// 更新配置(会自动触发监听器)
config.SetConfig("graphics.quality", quality);
@ -640,7 +641,7 @@ public class SettingsController : IController
public void ResetToDefaults()
{
var config = this.GetUtility<IConfigurationManager>();
var config = Context.GetUtility<IConfigurationManager>();
// 清空所有配置
config.Clear();

View File

@ -232,17 +232,18 @@ public class GameArchitecture : Architecture
using Arch.Core;
using GFramework.Core.Abstractions.controller;
using MyGame.Components;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
public class GameController : IController
[ContextAware]
public partial class GameController : IController
{
private World _world;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void Start()
{
// 获取 World
_world = this.GetService<World>();
_world = Context.GetService<World>();
// 创建玩家实体
var player = _world.Create(

View File

@ -353,22 +353,24 @@ public class CombatSystem : AbstractSystem
### Controller 中注册事件
```csharp
public class GameController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
private IUnRegisterList _unregisterList = new UnRegisterList();
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void Initialize()
{
// 注册多个事件
this.RegisterEvent<GameStartedEvent>(OnGameStarted)
Context.RegisterEvent<GameStartedEvent>(OnGameStarted)
.AddToUnregisterList(_unregisterList);
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied)
Context.RegisterEvent<PlayerDiedEvent>(OnPlayerDied)
.AddToUnregisterList(_unregisterList);
this.RegisterEvent<LevelCompletedEvent>(OnLevelCompleted)
Context.RegisterEvent<LevelCompletedEvent>(OnLevelCompleted)
.AddToUnregisterList(_unregisterList);
}
@ -417,7 +419,7 @@ onAnyDamage.Register(() =>
```csharp
// 只处理高伤害事件
this.RegisterEvent<DamageDealtEvent>(e =>
Context.RegisterEvent<DamageDealtEvent>(e =>
{
if (e.Damage >= 50)
{
@ -449,15 +451,17 @@ public class EventBridge : AbstractSystem
### 4. 临时事件监听
```csharp
public class TutorialController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class TutorialController : IController
{
public void Initialize()
{
// 只监听一次
IUnRegister unregister = null;
unregister = this.RegisterEvent<FirstEnemyKilledEvent>(e =>
unregister = Context.RegisterEvent<FirstEnemyKilledEvent>(e =>
{
ShowTutorialComplete();
unregister?.UnRegister(); // 立即注销
@ -497,7 +501,11 @@ public class AchievementSystem : AbstractSystem
### 使用 UnRegisterList
```csharp
public class MyController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class MyController : IController
{
// 统一管理所有注销对象
private IUnRegisterList _unregisterList = new UnRegisterList();
@ -505,10 +513,10 @@ public class MyController : IController
public void Initialize()
{
// 所有注册都添加到列表
this.RegisterEvent<Event1>(OnEvent1)
Context.RegisterEvent<Event1>(OnEvent1)
.AddToUnregisterList(_unregisterList);
this.RegisterEvent<Event2>(OnEvent2)
Context.RegisterEvent<Event2>(OnEvent2)
.AddToUnregisterList(_unregisterList);
}

View File

@ -109,16 +109,17 @@ event Action<PauseGroup, bool>? OnPauseStateChanged;
### 1. 获取暂停管理器
```csharp
public class GameController : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void Initialize()
{
// 从架构中获取暂停管理器
_pauseManager = this.GetUtility<IPauseStackManager>();
_pauseManager = Context.GetUtility<IPauseStackManager>();
}
}
```
@ -126,16 +127,17 @@ public class GameController : IController
### 2. 简单的暂停/恢复
```csharp
public class PauseMenuController : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PauseMenuController : IController
{
private IPauseStackManager _pauseManager;
private PauseToken _pauseToken;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void Initialize()
{
_pauseManager = this.GetUtility<IPauseStackManager>();
_pauseManager = Context.GetUtility<IPauseStackManager>();
}
public void OpenPauseMenu()
@ -161,12 +163,13 @@ public class PauseMenuController : IController
### 3. 使用作用域自动管理
```csharp
public class DialogController : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class DialogController : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void ShowDialog(string message)
{
// 使用 using 语法,自动管理暂停生命周期
@ -212,12 +215,13 @@ public class GameplaySystem : AbstractSystem
### 1. 嵌套暂停
```csharp
public class UIManager : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class UIManager : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void ShowNestedMenus()
{
// 第一层:主菜单
@ -250,12 +254,13 @@ public class UIManager : IController
### 2. 分组暂停
```csharp
public class GameManager : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameManager : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void OpenInventory()
{
// 只暂停游戏逻辑UI 和音频继续运行
@ -357,15 +362,16 @@ public class GameInitializer
### 4. 监听暂停状态变化
```csharp
public class PauseIndicator : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PauseIndicator : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void Initialize()
{
_pauseManager = this.GetUtility<IPauseStackManager>();
_pauseManager = Context.GetUtility<IPauseStackManager>();
// 订阅状态变化事件
_pauseManager.OnPauseStateChanged += OnPauseStateChanged;
@ -398,12 +404,13 @@ public class PauseIndicator : IController
### 5. 调试暂停状态
```csharp
public class PauseDebugger : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PauseDebugger : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void PrintPauseStatus()
{
Console.WriteLine("=== 暂停状态 ===");
@ -434,12 +441,13 @@ public class PauseDebugger : IController
### 6. 紧急恢复
```csharp
public class EmergencyController : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class EmergencyController : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void ForceResumeAll()
{
// 清空所有暂停请求(谨慎使用)
@ -674,16 +682,17 @@ public class ThreadSafeUsage
在组件销毁时注销处理器和事件:
```csharp
public class ProperCleanup : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class ProperCleanup : IController
{
private IPauseStackManager _pauseManager;
private IPauseHandler _customHandler;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void Initialize()
{
_pauseManager = this.GetUtility<IPauseStackManager>();
_pauseManager = Context.GetUtility<IPauseStackManager>();
_customHandler = new CustomPauseHandler();
_pauseManager.RegisterHandler(_customHandler);
@ -775,12 +784,13 @@ public class SelectiveSystem : AbstractSystem
A: 暂停系统控制是否执行,时间缩放需要使用时间系统:
```csharp
public class SlowMotionController : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class SlowMotionController : IController
{
private ITimeProvider _timeProvider;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void EnableSlowMotion()
{
// 使用时间缩放而不是暂停
@ -819,12 +829,13 @@ _pauseManager.Push("AI 系统", PauseGroup.Custom3);
A: 使用 `PauseScope` 配合 `async/await`
```csharp
public class AsyncPauseExample : IController
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class AsyncPauseExample : IController
{
private IPauseStackManager _pauseManager;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public async Task ShowAsyncDialog()
{
using (_pauseManager.PauseScope("异步对话框"))

View File

@ -198,6 +198,10 @@ public class PlayerModel : AbstractModel
### UI 数据绑定
```csharp
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PlayerUI : Control, IController
{
[Export] private Label _healthLabel;
@ -206,11 +210,9 @@ public partial class PlayerUI : Control, IController
private IUnRegisterList _unregisterList = new UnRegisterList();
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public override void _Ready()
{
var playerModel = this.GetModel<PlayerModel>();
var playerModel = Context.GetModel<PlayerModel>();
// 绑定生命值到UI立即显示当前值
playerModel.Health
@ -269,13 +271,14 @@ public class SettingsModel : AbstractModel
}
// UI Controller
[ContextAware]
public partial class VolumeSlider : HSlider, IController
{
private BindableProperty<float> _volumeProperty;
public override void _Ready()
{
_volumeProperty = this.GetModel<SettingsModel>().MasterVolume;
_volumeProperty = Context.GetModel<SettingsModel>().MasterVolume;
// Model -> UI
_volumeProperty.RegisterWithInitValue(vol => Value = vol)
@ -339,11 +342,15 @@ public class PlayerModel : AbstractModel
### 4. 条件监听
```c#
public class CombatController : Node, IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class CombatController : Node, IController
{
public override void _Ready()
{
var playerModel = this.GetModel<PlayerModel>();
var playerModel = Context.GetModel<PlayerModel>();
// 只在生命值低于30%时显示警告
playerModel.Health.Register(hp =>

View File

@ -144,13 +144,15 @@ public class LoadPlayerDataQuery : AbstractAsyncQuery<LoadPlayerDataInput, Playe
### 2. 发送查询
```csharp
public class ShopUI : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class ShopUI : IController
{
[Export] private Button _buyButton;
[Export] private int _itemPrice = 100;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void OnReady()
{
_buyButton.Pressed += OnBuyButtonPressed;
@ -160,12 +162,12 @@ public class ShopUI : IController
{
// 查询玩家金币
var query = new GetPlayerGoldQuery { Input = new GetPlayerGoldInput() };
int playerGold = this.SendQuery(query);
int playerGold = Context.SendQuery(query);
if (playerGold >= _itemPrice)
{
// 发送购买命令
this.SendCommand(new BuyItemCommand { Input = new BuyItemInput { ItemId = "sword_01" } });
Context.SendCommand(new BuyItemCommand { Input = new BuyItemInput { ItemId = "sword_01" } });
}
else
{

View File

@ -128,13 +128,15 @@ public class GameArchitecture : Architecture
### 切换状态
```csharp
public class GameController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
public async Task StartGame()
{
var stateMachine = this.GetSystem<IStateMachineSystem>();
var stateMachine = Context.GetSystem<IStateMachineSystem>();
// 切换到游戏状态
var success = await stateMachine.ChangeToAsync<GameplayState>();
@ -218,11 +220,15 @@ public class LoadingState : AsyncContextAwareStateBase
### 状态历史和回退
```csharp
public class GameController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
public async Task NavigateBack()
{
var stateMachine = this.GetSystem<IStateMachineSystem>();
var stateMachine = Context.GetSystem<IStateMachineSystem>();
// 回退到上一个状态
var success = await stateMachine.GoBackAsync();
@ -235,7 +241,7 @@ public class GameController : IController
public void ShowHistory()
{
var stateMachine = this.GetSystem<IStateMachineSystem>();
var stateMachine = Context.GetSystem<IStateMachineSystem>();
// 获取状态历史
var history = stateMachine.GetStateHistory();

View File

@ -185,15 +185,17 @@ public class GameArchitecture : Architecture
```csharp
// 在 Controller 中
public class GameController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
public void Start()
{
// 获取 System
var combatSystem = this.GetSystem<CombatSystem>();
var questSystem = this.GetSystem<QuestSystem>();
var combatSystem = Context.GetSystem<CombatSystem>();
var questSystem = Context.GetSystem<QuestSystem>();
// 使用 System
combatSystem.StartBattle();

View File

@ -102,13 +102,15 @@ public class SaveData : IVersionedData
### 使用存档仓库
```csharp
public class SaveController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class SaveController : IController
{
public async Task SaveGame(int slot)
{
var saveRepo = this.GetUtility<ISaveRepository<SaveData>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveData>>();
// 创建存档数据
var saveData = new SaveData
@ -129,7 +131,7 @@ public class SaveController : IController
public async Task LoadGame(int slot)
{
var saveRepo = this.GetUtility<ISaveRepository<SaveData>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveData>>();
// 检查存档是否存在
if (!await saveRepo.ExistsAsync(slot))
@ -145,7 +147,7 @@ public class SaveController : IController
public async Task DeleteSave(int slot)
{
var saveRepo = this.GetUtility<ISaveRepository<SaveData>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveData>>();
// 删除存档
await saveRepo.DeleteAsync(slot);
@ -188,7 +190,7 @@ public class GameArchitecture : Architecture
```csharp
public async Task ShowSaveList()
{
var saveRepo = this.GetUtility<ISaveRepository<SaveData>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveData>>();
// 获取所有存档槽位
var slots = await saveRepo.ListSlotsAsync();
@ -207,7 +209,11 @@ public async Task ShowSaveList()
### 自动保存
```csharp
public class AutoSaveController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class AutoSaveController : IController
{
private CancellationTokenSource? _autoSaveCts;
@ -243,7 +249,7 @@ public class AutoSaveController : IController
private async Task SaveGame(int slot)
{
var saveRepo = this.GetUtility<ISaveRepository<SaveData>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveData>>();
var saveData = CreateSaveData();
await saveRepo.SaveAsync(slot, saveData);
}
@ -296,7 +302,7 @@ public class SaveDataMigrator
// 加载时自动迁移
public async Task<SaveDataV2> LoadWithMigration(int slot)
{
var saveRepo = this.GetUtility<ISaveRepository<SaveDataV2>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveDataV2>>();
var data = await saveRepo.LoadAsync(slot);
if (data.Version < 2)
@ -318,11 +324,15 @@ public async Task<SaveDataV2> LoadWithMigration(int slot)
### 使用数据仓库
```csharp
public class SettingsController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class SettingsController : IController
{
public async Task SaveSettings()
{
var dataRepo = this.GetUtility<IDataRepository>();
var dataRepo = Context.GetUtility<IDataRepository>();
var settings = new GameSettings
{
@ -340,7 +350,7 @@ public class SettingsController : IController
public async Task<GameSettings> LoadSettings()
{
var dataRepo = this.GetUtility<IDataRepository>();
var dataRepo = Context.GetUtility<IDataRepository>();
var location = new DataLocation("settings", "game_settings.json");
// 检查是否存在
@ -360,7 +370,7 @@ public class SettingsController : IController
```csharp
public async Task SaveAllGameData()
{
var dataRepo = this.GetUtility<IDataRepository>();
var dataRepo = Context.GetUtility<IDataRepository>();
var dataList = new List<(IDataLocation, IData)>
{
@ -380,7 +390,7 @@ public async Task SaveAllGameData()
```csharp
public async Task BackupSave(int slot)
{
var saveRepo = this.GetUtility<ISaveRepository<SaveData>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveData>>();
if (!await saveRepo.ExistsAsync(slot))
{
@ -401,7 +411,7 @@ public async Task BackupSave(int slot)
public async Task RestoreBackup(int slot)
{
int backupSlot = slot + 100;
var saveRepo = this.GetUtility<ISaveRepository<SaveData>>();
var saveRepo = Context.GetUtility<ISaveRepository<SaveData>>();
if (!await saveRepo.ExistsAsync(backupSlot))
{

View File

@ -164,13 +164,15 @@ public class GameSceneRegistry : IGameSceneRegistry
使用场景路由进行导航:
```csharp
public class GameController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
public async Task StartGame()
{
var sceneRouter = this.GetSystem<ISceneRouter>();
var sceneRouter = Context.GetSystem<ISceneRouter>();
// 替换当前场景(清空场景栈)
await sceneRouter.ReplaceAsync("Gameplay");
@ -178,7 +180,7 @@ public class GameController : IController
public async Task ShowPauseMenu()
{
var sceneRouter = this.GetSystem<ISceneRouter>();
var sceneRouter = Context.GetSystem<ISceneRouter>();
// 压入新场景(保留当前场景)
await sceneRouter.PushAsync("Pause");
@ -186,7 +188,7 @@ public class GameController : IController
public async Task ClosePauseMenu()
{
var sceneRouter = this.GetSystem<ISceneRouter>();
var sceneRouter = Context.GetSystem<ISceneRouter>();
// 弹出当前场景(恢复上一个场景)
await sceneRouter.PopAsync();
@ -350,13 +352,15 @@ sceneRouter.AddTransitionHandler(new FadeTransitionHandler());
### 场景栈管理
```csharp
public class SceneNavigationController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class SceneNavigationController : IController
{
public async Task NavigateToSettings()
{
var sceneRouter = this.GetSystem<ISceneRouter>();
var sceneRouter = Context.GetSystem<ISceneRouter>();
// 检查场景是否已在栈中
if (sceneRouter.Contains("Settings"))
@ -371,7 +375,7 @@ public class SceneNavigationController : IController
public void ShowSceneStack()
{
var sceneRouter = this.GetSystem<ISceneRouter>();
var sceneRouter = Context.GetSystem<ISceneRouter>();
Console.WriteLine("当前场景栈:");
foreach (var scene in sceneRouter.Stack)
@ -382,7 +386,7 @@ public class SceneNavigationController : IController
public async Task ReturnToMainMenu()
{
var sceneRouter = this.GetSystem<ISceneRouter>();
var sceneRouter = Context.GetSystem<ISceneRouter>();
// 清空所有场景并加载主菜单
await sceneRouter.ClearAsync();
@ -432,13 +436,15 @@ public class GameplayScene : IScene
### 场景预加载
```csharp
public class PreloadController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PreloadController : IController
{
public async Task PreloadNextLevel()
{
var sceneFactory = this.GetUtility<ISceneFactory>();
var sceneFactory = Context.GetUtility<ISceneFactory>();
// 预加载下一关场景
var scene = sceneFactory.Create("Level2");
@ -556,7 +562,7 @@ await sceneRouter.ReplaceAsync("Gameplay", new GameplayEnterParam
2. **通过 Model**
```csharp
var gameModel = this.GetModel<GameModel>();
var gameModel = Context.GetModel<GameModel>();
gameModel.CurrentLevel = 5;
await sceneRouter.ReplaceAsync("Gameplay");
```
@ -564,7 +570,7 @@ await sceneRouter.ReplaceAsync("Gameplay");
3. **通过事件**
```csharp
this.SendEvent(new LevelSelectedEvent { Level = 5 });
Context.SendEvent(new LevelSelectedEvent { Level = 5 });
await sceneRouter.ReplaceAsync("Gameplay");
```
@ -598,7 +604,7 @@ public class LoadingScreenHandler : ISceneTransitionHandler
```csharp
public async Task ChangeScene(string sceneKey)
{
var sceneRouter = this.GetSystem<ISceneRouter>();
var sceneRouter = Context.GetSystem<ISceneRouter>();
if (sceneRouter.IsTransitioning)
{
@ -635,7 +641,7 @@ catch (Exception ex)
```csharp
// 在当前场景中预加载下一个场景
var factory = this.GetUtility<ISceneFactory>();
var factory = Context.GetUtility<ISceneFactory>();
var nextScene = factory.Create("NextLevel");
await nextScene.OnLoadAsync(null);

View File

@ -94,6 +94,8 @@ public class GameArchitecture : Architecture
使用泛型 API 序列化对象:
```csharp
using GFramework.SourceGenerators.Abstractions.rule;
public class PlayerData
{
public string Name { get; set; }
@ -101,13 +103,12 @@ public class PlayerData
public int Experience { get; set; }
}
public class SaveController : IController
[ContextAware]
public partial class SaveController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void SavePlayer()
{
var serializer = this.GetUtility<ISerializer>();
var serializer = Context.GetUtility<ISerializer>();
var player = new PlayerData
{
@ -131,7 +132,7 @@ public class SaveController : IController
```csharp
public void LoadPlayer()
{
var serializer = this.GetUtility<ISerializer>();
var serializer = Context.GetUtility<ISerializer>();
string json = "{\"Name\":\"Player1\",\"Level\":10,\"Experience\":1000}";
@ -149,7 +150,7 @@ public void LoadPlayer()
```csharp
public void SerializeRuntimeType()
{
var serializer = this.GetUtility<IRuntimeTypeSerializer>();
var serializer = Context.GetUtility<IRuntimeTypeSerializer>();
object data = new PlayerData { Name = "Player1", Level = 10 };
Type dataType = data.GetType();
@ -174,15 +175,15 @@ public void SerializeRuntimeType()
```csharp
using GFramework.Core.Abstractions.storage;
using GFramework.Game.storage;
using GFramework.SourceGenerators.Abstractions.rule;
public class DataManager : IController
[ContextAware]
public partial class DataManager : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public async Task SaveData()
{
var serializer = this.GetUtility<ISerializer>();
var storage = this.GetUtility<IStorage>();
var serializer = Context.GetUtility<ISerializer>();
var storage = Context.GetUtility<IStorage>();
var gameData = new GameData
{
@ -199,8 +200,8 @@ public class DataManager : IController
public async Task<GameData> LoadData()
{
var serializer = this.GetUtility<ISerializer>();
var storage = this.GetUtility<IStorage>();
var serializer = Context.GetUtility<ISerializer>();
var storage = Context.GetUtility<IStorage>();
// 从存储读取
string json = await storage.ReadAsync<string>("game_data");

View File

@ -126,13 +126,15 @@ public class MainMenuPage : IUiPage
使用 UI 路由进行导航:
```csharp
public class UiController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class UiController : IController
{
public async Task ShowSettings()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 压入设置页面(保留当前页面)
await uiRouter.PushAsync("Settings");
@ -140,7 +142,7 @@ public class UiController : IController
public async Task CloseSettings()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 弹出当前页面(返回上一页)
await uiRouter.PopAsync();
@ -148,7 +150,7 @@ public class UiController : IController
public async Task ShowMainMenu()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 替换所有页面(清空 UI 栈)
await uiRouter.ReplaceAsync("MainMenu");
@ -159,13 +161,12 @@ public class UiController : IController
### 显示不同层级的 UI
```csharp
public class UiController : IController
[ContextAware]
public partial class UiController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public void ShowDialog()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 在 Modal 层显示对话框
var handle = uiRouter.Show("ConfirmDialog", UiLayer.Modal);
@ -173,7 +174,7 @@ public class UiController : IController
public void ShowToast(string message)
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 在 Toast 层显示提示
var handle = uiRouter.Show("ToastMessage", UiLayer.Toast,
@ -182,7 +183,7 @@ public class UiController : IController
public void ShowLoading()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 在 Topmost 层显示加载界面
var handle = uiRouter.Show("LoadingScreen", UiLayer.Topmost);
@ -303,13 +304,17 @@ uiRouter.RegisterHandler(new FadeTransitionHandler());
### UI 句柄管理
```csharp
public class DialogController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class DialogController : IController
{
private UiHandle? _dialogHandle;
public void ShowDialog()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 显示对话框并保存句柄
_dialogHandle = uiRouter.Show("ConfirmDialog", UiLayer.Modal);
@ -319,7 +324,7 @@ public class DialogController : IController
{
if (_dialogHandle.HasValue)
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 使用句柄关闭对话框
uiRouter.Hide(_dialogHandle.Value, UiLayer.Modal, destroy: true);
@ -332,11 +337,15 @@ public class DialogController : IController
### UI 栈管理
```csharp
public class NavigationController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class NavigationController : IController
{
public void ShowUiStack()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
Console.WriteLine($"UI 栈深度: {uiRouter.Count}");
@ -349,13 +358,13 @@ public class NavigationController : IController
public bool IsSettingsOpen()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
return uiRouter.Contains("Settings");
}
public bool IsTopPage(string uiKey)
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
return uiRouter.IsTop(uiKey);
}
}
@ -364,11 +373,15 @@ public class NavigationController : IController
### 多层级 UI 管理
```csharp
public class LayerController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class LayerController : IController
{
public void ShowMultipleToasts()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// Toast 层支持重入,可以同时显示多个
uiRouter.Show("Toast1", UiLayer.Toast);
@ -378,7 +391,7 @@ public class LayerController : IController
public void ClearAllToasts()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 清空 Toast 层的所有 UI
uiRouter.ClearLayer(UiLayer.Toast, destroy: true);
@ -386,7 +399,7 @@ public class LayerController : IController
public void HideAllDialogs()
{
var uiRouter = this.GetSystem<IUiRouter>();
var uiRouter = Context.GetSystem<IUiRouter>();
// 隐藏 Modal 层的所有对话框
uiRouter.HideByKey("ConfirmDialog", UiLayer.Modal, hideAll: true);

View File

@ -151,17 +151,19 @@ public class EnemyDamagedEvent : IEvent
实现控制器来连接 UI 和业务逻辑:
```csharp
public class GameController : IController
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class GameController : IController
{
private IArchitecture _architecture;
private PlayerModel _playerModel;
private GameStateModel _gameStateModel;
public GameController(IArchitecture architecture)
public void Initialize()
{
_architecture = architecture;
_playerModel = architecture.GetModel<PlayerModel>();
_gameStateModel = architecture.GetModel<GameStateModel>();
_playerModel = Context.GetModel<PlayerModel>();
_gameStateModel = Context.GetModel<GameStateModel>();
// 初始化事件监听
InitializeEventListeners();
@ -178,18 +180,18 @@ public class GameController : IController
public void StartGame()
{
_gameStateModel.IsGameRunning.Value = true;
_architecture.SendEvent(new GameStartEvent());
Context.SendEvent(new GameStartEvent());
Console.WriteLine("Game started!");
}
public void MovePlayer(Vector2 direction)
{
_architecture.SendCommand(new MovePlayerCommand { Direction = direction });
Context.SendCommand(new MovePlayerCommand { Direction = direction });
}
public void PlayerAttack(Vector2 target)
{
_architecture.SendCommand(new AttackCommand { TargetPosition = target });
Context.SendCommand(new AttackCommand { TargetPosition = target });
}
// UI 更新回调
@ -270,7 +272,8 @@ class Program
architecture.Initialize();
// 创建控制器
var gameController = new GameController(architecture);
var gameController = new GameController();
gameController.Initialize();
// 开始游戏
gameController.StartGame();

View File

@ -340,27 +340,32 @@ public class GameArchitecture : AbstractArchitecture
```csharp
using Godot;
using GFramework.Godot.extensions;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
public partial class Player : CharacterBody2D
[ContextAware]
public partial class Player : CharacterBody2D, IController
{
public override void _Ready()
{
// 通过扩展方法访问架构组件
var playerModel = this.GetModel<PlayerModel>();
var gameplaySystem = this.GetSystem<GameplaySystem>();
// 方式 1: 通过 Context 属性访问(由 [ContextAware] 生成)
var playerModel = Context.GetModel<PlayerModel>();
var gameplaySystem = Context.GetSystem<GameplaySystem>();
// 方式 2: 通过扩展方法访问(扩展方法基于 IContextAware
var playerModel2 = this.GetModel<PlayerModel>();
// 发送事件
this.SendEvent(new PlayerSpawnedEvent());
Context.SendEvent(new PlayerSpawnedEvent());
// 执行命令
this.SendCommand(new InitPlayerCommand());
Context.SendCommand(new InitPlayerCommand());
}
public override void _Process(double delta)
{
// 在 Process 中使用架构组件
var inputSystem = this.GetSystem<InputSystem>();
var inputSystem = Context.GetSystem<InputSystem>();
var movement = inputSystem.GetMovementInput();
Velocity = movement * 200;
@ -407,14 +412,24 @@ public class UiArchitecture : AbstractArchitecture
}
// 在不同节点中使用不同架构
[ContextAware]
public partial class GameNode : Node, IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
// 配置使用 GameArchitecture 的上下文提供者
static GameNode()
{
SetContextProvider(new GameContextProvider());
}
}
[ContextAware]
public partial class UiNode : Control, IController
{
public IArchitecture GetArchitecture() => UiArchitecture.Interface;
// 配置使用 UiArchitecture 的上下文提供者
static UiNode()
{
SetContextProvider(new UiContextProvider());
}
}
```
@ -504,17 +519,23 @@ public partial class GameRoot : Node
### 问题:如何在节点中访问架构?
**解答**
实现 `IController` 接口或使用扩展方法
使用 `[ContextAware]` 特性或直接使用单例
```csharp
// 方式 1: 实现 IController
using GFramework.SourceGenerators.Abstractions.rule;
// 方式 1: 使用 [ContextAware] 特性(推荐)
[ContextAware]
public partial class Player : Node, IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public override void _Ready()
{
var model = this.GetModel<PlayerModel>();
// 通过 Context 属性访问架构(由 [ContextAware] 生成)
var model = Context.GetModel<PlayerModel>();
var system = Context.GetSystem<GameplaySystem>();
// 或使用扩展方法(扩展方法基于 IContextAware
var model2 = this.GetModel<PlayerModel>();
}
}
@ -528,6 +549,13 @@ public partial class Enemy : Node
}
```
**注意**
- `IController` 是标记接口,不包含任何方法
- 架构访问能力由 `[ContextAware]` 特性提供
- `[ContextAware]` 会自动生成 `Context` 属性和实现 `IContextAware` 接口
- 扩展方法(如 `this.GetModel()`)基于 `IContextAware` 接口,而非 `IController`
### 问题:架构锚点节点是什么?
**解答**

View File

@ -227,6 +227,32 @@ public partial class GameFlowController : IController
}
```
### 与 IController 配合使用
在 Godot 项目中,控制器通常同时实现 `IController` 和使用 `[ContextAware]`
```csharp
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PlayerController : Node, IController
{
public override void _Ready()
{
// Context 属性由 [ContextAware] 自动生成
var playerModel = Context.GetModel<PlayerModel>();
var combatSystem = Context.GetSystem<CombatSystem>();
}
}
```
**说明**
- `IController` 是标记接口,标识这是一个控制器
- `[ContextAware]` 提供架构访问能力
- 两者配合使用是推荐的模式
### 何时继承 ContextAwareBase
如果类需要更多框架功能(如生命周期管理),应继承 `ContextAwareBase`

View File

@ -164,8 +164,8 @@ public static partial class MathHelper
### 基础使用
```csharp
using GFramework.SourceGenerators.Abstractions.rule;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
[ContextAware]
public partial class PlayerController : IController
@ -272,6 +272,10 @@ public async Task TestPlayerController()
### 与其他属性组合
```csharp
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.logging;
using GFramework.SourceGenerators.Abstractions.rule;
[Log]
[ContextAware]
public partial class AdvancedController : IController
@ -506,8 +510,9 @@ public class InefficientController : IController
### 完整的游戏控制器示例
```csharp
using GFramework.SourceGenerators.Attributes;
using GFramework.Core.Abstractions;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.logging;
using GFramework.SourceGenerators.Abstractions.rule;
[Log]
[ContextAware]
@ -595,6 +600,10 @@ public enum CharacterState
Dead
}
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.logging;
using GFramework.SourceGenerators.Abstractions.rule;
[Log]
[ContextAware]
public partial class CharacterController : Node, IController

View File

@ -164,6 +164,10 @@ public partial class MySystem : AbstractSystem
### 游戏控制器
```csharp
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.logging;
using GFramework.SourceGenerators.Abstractions.rule;
[Log]
[ContextAware]
public partial class PlayerController : IController

View File

@ -473,14 +473,15 @@ namespace MyShooterGame.Systems
```csharp
// Scripts/Controllers/PlayerController.cs
using GFramework.Core.Abstractions.controller;
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.extensions;
using GFramework.SourceGenerators.Abstractions.rule;
using MyShooterGame.Architecture;
using MyShooterGame.Models;
using Godot;
namespace MyShooterGame.Controllers
{
[ContextAware]
public partial class PlayerController : CharacterBody2D, IController
{
[Export] public float Speed = 300f;
@ -489,12 +490,10 @@ namespace MyShooterGame.Controllers
private float _shootCooldown = 0f;
private const float ShootInterval = 0.2f;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public override void _Ready()
{
// 监听玩家死亡
var playerModel = this.GetModel<PlayerModel>();
// 监听玩家死亡(通过 Context 属性访问架构)
var playerModel = Context.GetModel<PlayerModel>();
playerModel.IsAlive.RegisterOnValueChanged(isAlive =>
{
if (!isAlive)
@ -630,15 +629,14 @@ public partial class Main : Node
// Scripts/UI/MenuController.cs
using Godot;
using GFramework.Core.Abstractions.controller;
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.extensions;
using GFramework.SourceGenerators.Abstractions.rule;
using MyShooterGame.Architecture;
using MyShooterGame.Systems;
[ContextAware]
public partial class MenuController : Control, IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public override void _Ready()
{
// 连接按钮信号
@ -650,8 +648,8 @@ public partial class MenuController : Control, IController
{
GD.Print("开始游戏");
// 初始化游戏
var gameplaySystem = this.GetSystem<GameplaySystem>();
// 初始化游戏(通过 Context 属性访问架构)
var gameplaySystem = Context.GetSystem<GameplaySystem>();
gameplaySystem.StartNewGame();
// 切换到游戏场景
@ -675,27 +673,27 @@ using Godot;
using GFramework.Core.Abstractions.controller;
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.extensions;
using GFramework.SourceGenerators.Abstractions.rule;
using MyShooterGame.Architecture;
using MyShooterGame.Systems;
using MyShooterGame.Models;
[ContextAware]
public partial class GameScene : Node2D, IController
{
[Export] public PackedScene EnemyScene;
private SpawnSystem _spawnSystem;
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
public override void _Ready()
{
// 初始化生成系统
_spawnSystem = this.GetSystem<SpawnSystem>();
// 初始化生成系统(通过 Context 属性访问架构)
_spawnSystem = Context.GetSystem<SpawnSystem>();
_spawnSystem.Initialize(this, EnemyScene);
_spawnSystem.StartSpawning();
// 监听游戏状态
var gameModel = this.GetModel<GameModel>();
var gameModel = Context.GetModel<GameModel>();
gameModel.IsPlaying.RegisterOnValueChanged(isPlaying =>
{
if (!isPlaying)

View File

@ -323,24 +323,23 @@ namespace MyGame.Systems
```csharp
using GFramework.Core.Abstractions.pause;
using GFramework.Core.extensions;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
namespace MyGame.Controllers
{
/// <summary>
/// 暂停控制器,管理复杂的暂停场景
/// </summary>
public class PauseController : IController
[ContextAware]
public partial class PauseController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
/// <summary>
/// 显示暂停状态信息
/// </summary>
public void ShowPauseStatus()
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
Console.WriteLine("\n=== 暂停状态 ===");
Console.WriteLine($"全局暂停: {pauseManager.IsPaused(PauseGroup.Global)}");
@ -370,7 +369,7 @@ namespace MyGame.Controllers
/// </summary>
public void TestNestedPause()
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
Console.WriteLine("--- 测试嵌套暂停 ---\n");
@ -410,7 +409,7 @@ namespace MyGame.Controllers
/// </summary>
public void TestPauseScope()
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
Console.WriteLine("--- 测试暂停作用域 ---\n");
@ -438,7 +437,7 @@ namespace MyGame.Controllers
/// </summary>
public void EmergencyClearAll()
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
Console.WriteLine("⚠️ 紧急清除所有暂停状态");
pauseManager.ClearAll();
@ -451,7 +450,7 @@ namespace MyGame.Controllers
/// </summary>
public void ClearGroup(PauseGroup group)
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
Console.WriteLine($"清除 {group} 组的所有暂停");
pauseManager.ClearGroup(group);
@ -664,8 +663,8 @@ namespace MyGame
```csharp
using GFramework.Core.Abstractions.pause;
using GFramework.Core.extensions;
using GFramework.Core.Abstractions.controller;
using GFramework.SourceGenerators.Abstractions.rule;
using System.Threading.Tasks;
namespace MyGame.Controllers
@ -673,10 +672,9 @@ namespace MyGame.Controllers
/// <summary>
/// 游戏场景控制器
/// </summary>
public class GameSceneController : IController
[ContextAware]
public partial class GameSceneController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
private PauseToken? _pauseMenuToken;
private PauseToken? _dialogToken;
@ -685,7 +683,7 @@ namespace MyGame.Controllers
/// </summary>
public void TogglePauseMenu()
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
if (_pauseMenuToken.HasValue)
{
@ -707,7 +705,7 @@ namespace MyGame.Controllers
/// </summary>
public void ShowDialog(string message)
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
// 对话框使用全局暂停
_dialogToken = pauseManager.Push($"对话框: {message}", PauseGroup.Global);
@ -725,7 +723,7 @@ namespace MyGame.Controllers
return;
}
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
pauseManager.Pop(_dialogToken.Value);
_dialogToken = null;
Console.WriteLine("对话框已关闭");
@ -736,7 +734,7 @@ namespace MyGame.Controllers
/// </summary>
public async Task RunGameLoop()
{
var pauseManager = this.GetUtility<IPauseStackManager>();
var pauseManager = Context.GetUtility<IPauseStackManager>();
int frame = 0;
Console.WriteLine("\n=== 游戏循环开始 ===\n");

View File

@ -398,19 +398,19 @@ using GFramework.Core.Abstractions.state;
using GFramework.Core.extensions;
using MyGame.States;
using System.Threading.Tasks;
using GFramework.SourceGenerators.Abstractions.rule;
namespace MyGame.Controllers
{
public class GameFlowController : IController
[ContextAware]
public partial class GameFlowController : IController
{
public IArchitecture GetArchitecture() => GameArchitecture.Interface;
/// <summary>
/// 开始游戏
/// </summary>
public async Task StartGame(int level = 1)
{
var stateMachine = this.GetSystem<IStateMachineSystem>();
var stateMachine = Context.GetSystem<IStateMachineSystem>();
// 设置加载状态的目标关卡
var loadingState = stateMachine.GetState<LoadingState>();