From 32be23b01dd3920144e6ea015263da383e88c941 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Sun, 1 Feb 2026 10:35:11 +0800
Subject: [PATCH] =?UTF-8?q?feat(coroutine):=20=E6=B7=BB=E5=8A=A0=E5=91=BD?=
=?UTF-8?q?=E4=BB=A4=E5=92=8C=E6=9F=A5=E8=AF=A2=E7=9A=84=E5=8D=8F=E7=A8=8B?=
=?UTF-8?q?=E6=89=A9=E5=B1=95=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 实现了 CommandCoroutineExtensions 类,提供命令异步执行的协程包装
- 添加了 SendCommandCoroutineWithErrorHandler 方法处理命令执行异常
- 实现了 SendCommandAndWaitEventCoroutine 方法支持发送命令并等待事件
- 创建了 QueryCoroutineExtensions 类,提供查询操作的协程扩展
- 添加了 WaitForEvent 协程指令用于等待特定事件触发
- 实现了完整的事件监听和资源清理机制
---
.../extensions/CommandCoroutineExtensions.cs | 91 +++++++++++++++++++
.../extensions/QueryCoroutineExtensions.cs | 50 ++++++++++
.../coroutine/instructions/WaitForEvent.cs | 83 +++++++++++++++++
3 files changed, 224 insertions(+)
create mode 100644 GFramework.Core/coroutine/extensions/CommandCoroutineExtensions.cs
create mode 100644 GFramework.Core/coroutine/extensions/QueryCoroutineExtensions.cs
create mode 100644 GFramework.Core/coroutine/instructions/WaitForEvent.cs
diff --git a/GFramework.Core/coroutine/extensions/CommandCoroutineExtensions.cs b/GFramework.Core/coroutine/extensions/CommandCoroutineExtensions.cs
new file mode 100644
index 0000000..817b8c3
--- /dev/null
+++ b/GFramework.Core/coroutine/extensions/CommandCoroutineExtensions.cs
@@ -0,0 +1,91 @@
+// Copyright (c) 2026 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using GFramework.Core.Abstractions.command;
+using GFramework.Core.Abstractions.coroutine;
+using GFramework.Core.Abstractions.events;
+using GFramework.Core.Abstractions.rule;
+using GFramework.Core.coroutine.instructions;
+
+namespace GFramework.Core.coroutine.extensions;
+
+///
+/// 命令协程扩展方法类
+/// 提供将命令的异步执行包装为协程的功能
+///
+public static class CommandCoroutineExtensions
+{
+ ///
+ /// 将 Command 的异步执行包装为协程,并处理异常
+ ///
+ /// 命令类型,必须实现 IAsyncCommand 接口
+ /// 上下文感知对象
+ /// 要执行的命令实例
+ /// 错误回调处理
+ /// 返回协程指令枚举器
+ public static IEnumerator SendCommandCoroutineWithErrorHandler(
+ this IContextAware contextAware,
+ TCommand command,
+ Action? onError)
+ where TCommand : class, IAsyncCommand
+ {
+ var task = contextAware.GetContext().SendCommandAsync(command);
+
+ yield return task.AsCoroutineInstruction();
+
+ if (task.IsFaulted)
+ {
+ onError?.Invoke(task.Exception!);
+ }
+ }
+
+ ///
+ /// 发送 Command 并等待指定 Event
+ ///
+ public static IEnumerator SendCommandAndWaitEventCoroutine(
+ this IContextAware contextAware,
+ TCommand command,
+ Action? onEvent = null)
+ where TCommand : IAsyncCommand
+ where TEvent : class
+ {
+ var context = contextAware.GetContext();
+ var eventBus = context.GetService()!;
+
+ WaitForEvent? wait = null;
+
+ try
+ {
+ // 先注册事件监听器
+ wait = new WaitForEvent(eventBus);
+
+ // 发送异步命令并等待完成
+ var task = context.SendCommandAsync(command);
+ yield return task.AsCoroutineInstruction();
+
+ // 等待事件触发
+ yield return wait;
+
+ // 调用回调
+ if (onEvent != null && wait.EventData != null)
+ {
+ onEvent.Invoke(wait.EventData);
+ }
+ }
+ finally
+ {
+ // 确保清理事件监听器
+ wait?.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/coroutine/extensions/QueryCoroutineExtensions.cs b/GFramework.Core/coroutine/extensions/QueryCoroutineExtensions.cs
new file mode 100644
index 0000000..27f12dd
--- /dev/null
+++ b/GFramework.Core/coroutine/extensions/QueryCoroutineExtensions.cs
@@ -0,0 +1,50 @@
+// Copyright (c) 2026 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using GFramework.Core.Abstractions.coroutine;
+using GFramework.Core.Abstractions.query;
+using GFramework.Core.Abstractions.rule;
+
+namespace GFramework.Core.coroutine.extensions;
+
+///
+/// 查询协程扩展方法类
+/// 提供将查询操作包装为协程的扩展方法
+///
+public static class QueryCoroutineExtensions
+{
+ ///
+ /// 将 Query 包装为协程(立即返回结果)
+ ///
+ /// 查询类型,必须实现 IQuery<TResult> 接口
+ /// 查询结果类型
+ /// 上下文感知对象,用于获取执行上下文
+ /// 要执行的查询对象
+ /// 处理查询结果的回调方法
+ /// 返回一个协程迭代器,立即执行并返回结果
+ public static IEnumerator SendQueryCoroutine(
+ this IContextAware contextAware,
+ TQuery query,
+ Action onResult)
+ where TQuery : IQuery
+ {
+ // 执行查询并获取结果
+ var result = contextAware.GetContext().SendQuery(query);
+
+ // 调用结果处理回调
+ onResult(result);
+
+ // 协程立即结束
+ yield break;
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/coroutine/instructions/WaitForEvent.cs b/GFramework.Core/coroutine/instructions/WaitForEvent.cs
new file mode 100644
index 0000000..b267c0a
--- /dev/null
+++ b/GFramework.Core/coroutine/instructions/WaitForEvent.cs
@@ -0,0 +1,83 @@
+// Copyright (c) 2026 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using GFramework.Core.Abstractions.coroutine;
+using GFramework.Core.Abstractions.events;
+
+namespace GFramework.Core.coroutine.instructions;
+
+public sealed class WaitForEvent : IYieldInstruction, IDisposable
+{
+ private bool _disposed;
+ private volatile bool _done;
+ private TEvent? _eventData;
+ private IUnRegister? _unRegister;
+
+ ///
+ /// 初始化等待事件的指令
+ ///
+ /// 事件总线实例
+ public WaitForEvent(IEventBus eventBus)
+ {
+ var eventBus1 = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
+
+ // 注册事件监听器
+ _unRegister = eventBus1.Register(OnEventTriggered);
+ }
+
+ ///
+ /// 获取接收到的事件数据
+ ///
+ public TEvent? EventData => _eventData;
+
+ ///
+ /// 释放资源
+ ///
+ public void Dispose()
+ {
+ if (_disposed) return;
+
+ // 注销事件注册并清理资源
+ _unRegister?.UnRegister();
+ _unRegister = null;
+ _disposed = true;
+ }
+
+ ///
+ /// 获取等待是否已完成
+ ///
+ public bool IsDone => _done;
+
+ ///
+ /// 更新方法,用于处理时间更新逻辑
+ ///
+ /// 时间增量
+ public void Update(double deltaTime)
+ {
+ // 事件的完成由事件回调设置
+ // 如果已完成,确保注销事件监听器
+ if (!_done || _unRegister == null) return;
+ _unRegister.UnRegister();
+ _unRegister = null;
+ }
+
+ ///
+ /// 事件触发时的回调处理
+ ///
+ /// 事件数据
+ private void OnEventTriggered(TEvent eventData)
+ {
+ _eventData = eventData;
+ _done = true;
+ }
+}
\ No newline at end of file