mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-24 20:34:29 +08:00
feat(coroutine): 添加命令和查询的协程扩展功能
- 实现了 CommandCoroutineExtensions 类,提供命令异步执行的协程包装 - 添加了 SendCommandCoroutineWithErrorHandler 方法处理命令执行异常 - 实现了 SendCommandAndWaitEventCoroutine 方法支持发送命令并等待事件 - 创建了 QueryCoroutineExtensions 类,提供查询操作的协程扩展 - 添加了 WaitForEvent 协程指令用于等待特定事件触发 - 实现了完整的事件监听和资源清理机制
This commit is contained in:
parent
af64c4ab3e
commit
32be23b01d
@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 命令协程扩展方法类
|
||||||
|
/// 提供将命令的异步执行包装为协程的功能
|
||||||
|
/// </summary>
|
||||||
|
public static class CommandCoroutineExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将 Command 的异步执行包装为协程,并处理异常
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCommand">命令类型,必须实现 IAsyncCommand 接口</typeparam>
|
||||||
|
/// <param name="contextAware">上下文感知对象</param>
|
||||||
|
/// <param name="command">要执行的命令实例</param>
|
||||||
|
/// <param name="onError">错误回调处理</param>
|
||||||
|
/// <returns>返回协程指令枚举器</returns>
|
||||||
|
public static IEnumerator<IYieldInstruction> SendCommandCoroutineWithErrorHandler<TCommand>(
|
||||||
|
this IContextAware contextAware,
|
||||||
|
TCommand command,
|
||||||
|
Action<Exception>? onError)
|
||||||
|
where TCommand : class, IAsyncCommand
|
||||||
|
{
|
||||||
|
var task = contextAware.GetContext().SendCommandAsync(command);
|
||||||
|
|
||||||
|
yield return task.AsCoroutineInstruction();
|
||||||
|
|
||||||
|
if (task.IsFaulted)
|
||||||
|
{
|
||||||
|
onError?.Invoke(task.Exception!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送 Command 并等待指定 Event
|
||||||
|
/// </summary>
|
||||||
|
public static IEnumerator<IYieldInstruction> SendCommandAndWaitEventCoroutine<TCommand, TEvent>(
|
||||||
|
this IContextAware contextAware,
|
||||||
|
TCommand command,
|
||||||
|
Action<TEvent>? onEvent = null)
|
||||||
|
where TCommand : IAsyncCommand
|
||||||
|
where TEvent : class
|
||||||
|
{
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
var eventBus = context.GetService<IEventBus>()!;
|
||||||
|
|
||||||
|
WaitForEvent<TEvent>? wait = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 先注册事件监听器
|
||||||
|
wait = new WaitForEvent<TEvent>(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询协程扩展方法类
|
||||||
|
/// 提供将查询操作包装为协程的扩展方法
|
||||||
|
/// </summary>
|
||||||
|
public static class QueryCoroutineExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将 Query 包装为协程(立即返回结果)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TQuery">查询类型,必须实现 IQuery<TResult> 接口</typeparam>
|
||||||
|
/// <typeparam name="TResult">查询结果类型</typeparam>
|
||||||
|
/// <param name="contextAware">上下文感知对象,用于获取执行上下文</param>
|
||||||
|
/// <param name="query">要执行的查询对象</param>
|
||||||
|
/// <param name="onResult">处理查询结果的回调方法</param>
|
||||||
|
/// <returns>返回一个协程迭代器,立即执行并返回结果</returns>
|
||||||
|
public static IEnumerator<IYieldInstruction> SendQueryCoroutine<TQuery, TResult>(
|
||||||
|
this IContextAware contextAware,
|
||||||
|
TQuery query,
|
||||||
|
Action<TResult> onResult)
|
||||||
|
where TQuery : IQuery<TResult>
|
||||||
|
{
|
||||||
|
// 执行查询并获取结果
|
||||||
|
var result = contextAware.GetContext().SendQuery(query);
|
||||||
|
|
||||||
|
// 调用结果处理回调
|
||||||
|
onResult(result);
|
||||||
|
|
||||||
|
// 协程立即结束
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
}
|
||||||
83
GFramework.Core/coroutine/instructions/WaitForEvent.cs
Normal file
83
GFramework.Core/coroutine/instructions/WaitForEvent.cs
Normal file
@ -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<TEvent> : IYieldInstruction, IDisposable
|
||||||
|
{
|
||||||
|
private bool _disposed;
|
||||||
|
private volatile bool _done;
|
||||||
|
private TEvent? _eventData;
|
||||||
|
private IUnRegister? _unRegister;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化等待事件的指令
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventBus">事件总线实例</param>
|
||||||
|
public WaitForEvent(IEventBus eventBus)
|
||||||
|
{
|
||||||
|
var eventBus1 = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
|
||||||
|
|
||||||
|
// 注册事件监听器
|
||||||
|
_unRegister = eventBus1.Register<TEvent>(OnEventTriggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取接收到的事件数据
|
||||||
|
/// </summary>
|
||||||
|
public TEvent? EventData => _eventData;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放资源
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
|
||||||
|
// 注销事件注册并清理资源
|
||||||
|
_unRegister?.UnRegister();
|
||||||
|
_unRegister = null;
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取等待是否已完成
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDone => _done;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新方法,用于处理时间更新逻辑
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deltaTime">时间增量</param>
|
||||||
|
public void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
// 事件的完成由事件回调设置
|
||||||
|
// 如果已完成,确保注销事件监听器
|
||||||
|
if (!_done || _unRegister == null) return;
|
||||||
|
_unRegister.UnRegister();
|
||||||
|
_unRegister = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 事件触发时的回调处理
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventData">事件数据</param>
|
||||||
|
private void OnEventTriggered(TEvent eventData)
|
||||||
|
{
|
||||||
|
_eventData = eventData;
|
||||||
|
_done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user