mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
refactor(coroutine): 优化协程扩展中的异常处理和参数验证
- 修改了CommandCoroutineExtensions和MediatorCoroutineExtensions中的异常处理逻辑 - 添加了对负数超时参数的验证和异常抛出 - 改进了服务获取的空值检查机制 - 更新了文档注释以提供更清晰的参数说明 - 重构了SendCommandAndWaitEvent方法的实现结构 - 统一了错误消息格式和异常处理方式
This commit is contained in:
parent
b196cd40bb
commit
855b3f9eac
@ -43,19 +43,30 @@ public static class CommandCoroutineExtensions
|
||||
|
||||
yield return task.AsCoroutineInstruction();
|
||||
|
||||
if (task.IsFaulted) onError?.Invoke(task.Exception!);
|
||||
if (!task.IsFaulted) yield break;
|
||||
if (onError != null)
|
||||
onError.Invoke(task.Exception!);
|
||||
else
|
||||
throw task.Exception!.InnerException ?? task.Exception;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送 Command 并等待指定 Event
|
||||
/// 发送 Command 并等待指定 Event。
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand">命令类型,必须实现 IAsyncCommand 接口</typeparam>
|
||||
/// <typeparam name="TCommand">命令类型,必须实现 IAsyncCommand</typeparam>
|
||||
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||
/// <param name="contextAware">上下文感知对象</param>
|
||||
/// <param name="command">要执行的命令实例</param>
|
||||
/// <param name="onEvent">事件触发时的回调处理</param>
|
||||
/// <param name="timeout">等待超时时间(秒),0表示无限等待</param>
|
||||
/// <returns>返回协程指令枚举器</returns>
|
||||
/// <param name="timeout">
|
||||
/// 超时时间(秒):
|
||||
/// <list type="bullet">
|
||||
/// <item><description>timeout < 0: 无效,将抛出 ArgumentOutOfRangeException</description></item>
|
||||
/// <item><description>timeout == 0: 无超时,永久等待</description></item>
|
||||
/// <item><description>timeout > 0: 启用超时机制</description></item>
|
||||
/// </list>
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">当 timeout 小于 0 时抛出。</exception>
|
||||
public static IEnumerator<IYieldInstruction> SendCommandAndWaitEventCoroutine<TCommand, TEvent>(
|
||||
this IContextAware contextAware,
|
||||
TCommand command,
|
||||
@ -63,44 +74,64 @@ public static class CommandCoroutineExtensions
|
||||
float timeout = 0f)
|
||||
where TCommand : IAsyncCommand
|
||||
where TEvent : class
|
||||
{
|
||||
// 参数检查部分
|
||||
if (timeout < 0f)
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(timeout),
|
||||
timeout,
|
||||
"Timeout must be greater than or equal to 0.");
|
||||
|
||||
// 迭代器逻辑部分
|
||||
return SendCommandAndWaitEventIterator(contextAware, command, onEvent, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送 Command 并等待指定 Event 的迭代器实现。
|
||||
/// </summary>
|
||||
private static IEnumerator<IYieldInstruction> SendCommandAndWaitEventIterator<TCommand, TEvent>(
|
||||
IContextAware contextAware,
|
||||
TCommand command,
|
||||
Action<TEvent>? onEvent,
|
||||
float timeout)
|
||||
where TCommand : IAsyncCommand
|
||||
where TEvent : class
|
||||
{
|
||||
var context = contextAware.GetContext();
|
||||
var eventBus = context.GetService<IEventBus>()!;
|
||||
var eventBus = context.GetService<IEventBus>()
|
||||
?? throw new InvalidOperationException("IEventBus not found.");
|
||||
|
||||
WaitForEvent<TEvent>? wait = null;
|
||||
|
||||
try
|
||||
{
|
||||
// 先注册事件监听器
|
||||
// 先注册事件监听
|
||||
wait = new WaitForEvent<TEvent>(eventBus);
|
||||
|
||||
// 发送异步命令并等待完成
|
||||
// 发送命令
|
||||
var task = context.SendCommandAsync(command);
|
||||
yield return task.AsCoroutineInstruction();
|
||||
|
||||
// 如果有超时设置,使用超时等待
|
||||
// 等待事件
|
||||
if (timeout > 0f)
|
||||
{
|
||||
var timeoutWait = new WaitForEventWithTimeout<TEvent>(wait, timeout);
|
||||
yield return timeoutWait;
|
||||
|
||||
// 检查是否超时
|
||||
if (timeoutWait.IsTimeout)
|
||||
// 超时处理
|
||||
throw new TimeoutException($"wait for the event ${typeof(TEvent).Name} timeout.");
|
||||
throw new TimeoutException(
|
||||
$"Wait for event {typeof(TEvent).Name} timeout.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 等待事件触发(无超时)
|
||||
yield return wait;
|
||||
}
|
||||
|
||||
// 调用事件回调
|
||||
if (onEvent != null && wait.EventData != null) onEvent.Invoke(wait.EventData);
|
||||
if (wait.EventData != null)
|
||||
onEvent?.Invoke(wait.EventData);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 确保清理事件监听器
|
||||
wait?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026 GeWuYou
|
||||
// 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
|
||||
@ -47,20 +47,31 @@ public static class MediatorCoroutineExtensions
|
||||
|
||||
yield return task.AsCoroutineInstruction();
|
||||
|
||||
if (task.IsFaulted)
|
||||
onError?.Invoke(task.Exception!);
|
||||
if (!task.IsFaulted) yield break;
|
||||
if (onError != null)
|
||||
onError.Invoke(task.Exception!);
|
||||
else
|
||||
throw task.Exception!.InnerException ?? task.Exception;
|
||||
}
|
||||
|
||||
// ... existing code ...
|
||||
/// <summary>
|
||||
/// 发送命令并等待特定事件的协程实现,支持超时控制。
|
||||
/// 发送命令并等待特定事件的协程实现。
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand">命令的类型</typeparam>
|
||||
/// <typeparam name="TCommand">命令类型</typeparam>
|
||||
/// <typeparam name="TEvent">要等待的事件类型</typeparam>
|
||||
/// <param name="contextAware">上下文感知对象,用于获取服务</param>
|
||||
/// <param name="command">要发送的命令对象</param>
|
||||
/// <param name="onEvent">接收到事件时的回调处理函数</param>
|
||||
/// <param name="timeout">超时时间(秒),0表示无超时</param>
|
||||
/// <returns>协程枚举器,用于协程执行</returns>
|
||||
/// <param name="contextAware">上下文对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <param name="onEvent">事件触发时的回调</param>
|
||||
/// <param name="timeout">
|
||||
/// 超时时间(秒):
|
||||
/// <list type="bullet">
|
||||
/// <item><description>timeout < 0: 无效,将抛出 ArgumentOutOfRangeException</description></item>
|
||||
/// <item><description>timeout == 0: 无超时,永久等待</description></item>
|
||||
/// <item><description>timeout > 0: 启用超时机制</description></item>
|
||||
/// </list>
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">当 timeout 小于 0 时抛出。</exception>
|
||||
public static IEnumerator<IYieldInstruction> SendCommandAndWaitEventCoroutine<TCommand, TEvent>(
|
||||
this IContextAware contextAware,
|
||||
TCommand command,
|
||||
@ -69,10 +80,54 @@ public static class MediatorCoroutineExtensions
|
||||
where TCommand : notnull
|
||||
where TEvent : class
|
||||
{
|
||||
var context = contextAware.GetContext();
|
||||
var mediator = context.GetService<IMediator>()!;
|
||||
var eventBus = context.GetService<IEventBus>()!;
|
||||
// 参数验证
|
||||
ValidateParameters(timeout);
|
||||
|
||||
// 获取必要的服务
|
||||
var context = contextAware.GetContext();
|
||||
var mediator = context.GetService<IMediator>()
|
||||
?? throw new InvalidOperationException("IMediator not found.");
|
||||
var eventBus = context.GetService<IEventBus>()
|
||||
?? throw new InvalidOperationException("IEventBus not found.");
|
||||
|
||||
// 执行协程逻辑
|
||||
return ExecuteSendCommandAndWaitEventCoroutine(mediator, eventBus, command, onEvent, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证方法参数的有效性。
|
||||
/// </summary>
|
||||
/// <param name="timeout">超时时间</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">当 timeout 小于 0 时抛出。</exception>
|
||||
private static void ValidateParameters(float timeout)
|
||||
{
|
||||
if (timeout < 0f)
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(timeout),
|
||||
timeout,
|
||||
"Timeout must be greater than or equal to 0.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行发送命令并等待事件的协程逻辑。
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand">命令类型</typeparam>
|
||||
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||
/// <param name="mediator">中介者服务</param>
|
||||
/// <param name="eventBus">事件总线服务</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <param name="onEvent">事件回调</param>
|
||||
/// <param name="timeout">超时时间</param>
|
||||
/// <returns>协程枚举器</returns>
|
||||
private static IEnumerator<IYieldInstruction> ExecuteSendCommandAndWaitEventCoroutine<TCommand, TEvent>(
|
||||
IMediator mediator,
|
||||
IEventBus eventBus,
|
||||
TCommand command,
|
||||
Action<TEvent>? onEvent,
|
||||
float timeout)
|
||||
where TCommand : notnull
|
||||
where TEvent : class
|
||||
{
|
||||
WaitForEvent<TEvent>? wait = null;
|
||||
|
||||
try
|
||||
@ -80,7 +135,6 @@ public static class MediatorCoroutineExtensions
|
||||
wait = new WaitForEvent<TEvent>(eventBus);
|
||||
|
||||
var task = mediator.Send(command).AsTask();
|
||||
|
||||
yield return task.AsCoroutineInstruction();
|
||||
|
||||
if (timeout > 0f)
|
||||
@ -90,7 +144,7 @@ public static class MediatorCoroutineExtensions
|
||||
|
||||
if (timeoutWait.IsTimeout)
|
||||
throw new TimeoutException(
|
||||
$"wait for event {typeof(TEvent).Name} timeout.");
|
||||
$"Wait for event {typeof(TEvent).Name} timeout.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -105,4 +159,5 @@ public static class MediatorCoroutineExtensions
|
||||
wait?.Dispose();
|
||||
}
|
||||
}
|
||||
// ... existing code ...
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user