mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +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