mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-23 03:04:29 +08:00
feat(core): 扩展ContextAwareExtensions功能并增强状态机系统
- 在ContextAwareExtensions中添加事件发送、注册和取消注册方法 - 添加环境对象获取功能 - 扩展命令和查询功能支持同步、异步及中介者模式 - 添加统一请求处理方法和便捷扩展方法 - 为StateMachineSystem添加异步状态切换事件通知功能 - 添加状态机异步操作相关单元测试 - 扩展现有测试类以覆盖新增功能 - [release ci]
This commit is contained in:
parent
7e2a1ff66d
commit
f68a3f5385
@ -270,6 +270,93 @@ public class StateMachineSystemTests
|
||||
|
||||
_stateMachine.Destroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试异步ChangeToAsync发送StateChangedEvent事件
|
||||
/// 验证当状态机使用异步方法切换到新状态时,会正确触发StateChangedEvent事件
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_Should_Send_StateChangedEvent()
|
||||
{
|
||||
var eventReceived = false;
|
||||
StateChangedEvent? receivedEvent = null;
|
||||
|
||||
_eventBus!.Register<StateChangedEvent>(e =>
|
||||
{
|
||||
eventReceived = true;
|
||||
receivedEvent = e;
|
||||
});
|
||||
|
||||
var state1 = new TestStateV5();
|
||||
var state2 = new TestStateV5();
|
||||
|
||||
_stateMachine!.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
_stateMachine.Init();
|
||||
await _stateMachine.ChangeToAsync<TestStateV5>();
|
||||
|
||||
Assert.That(eventReceived, Is.True);
|
||||
Assert.That(receivedEvent!.OldState, Is.Null);
|
||||
Assert.That(receivedEvent.NewState, Is.InstanceOf<TestStateV5>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试异步ChangeToAsync发送StateChangedEvent事件(包含旧状态)
|
||||
/// 验证当状态机使用异步方法从一个状态切换到另一个状态时,会正确触发StateChangedEvent事件
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_Should_Send_StateChangedEvent_With_OldState()
|
||||
{
|
||||
var eventReceived = false;
|
||||
StateChangedEvent? receivedEvent = null;
|
||||
|
||||
_eventBus!.Register<StateChangedEvent>(e =>
|
||||
{
|
||||
eventReceived = true;
|
||||
receivedEvent = e;
|
||||
});
|
||||
|
||||
var state1 = new TestStateV5();
|
||||
var state2 = new TestStateV5_2();
|
||||
|
||||
_stateMachine!.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
_stateMachine.Init();
|
||||
await _stateMachine.ChangeToAsync<TestStateV5>();
|
||||
|
||||
eventReceived = false;
|
||||
await _stateMachine.ChangeToAsync<TestStateV5_2>();
|
||||
|
||||
Assert.That(eventReceived, Is.True);
|
||||
Assert.That(receivedEvent!.OldState, Is.InstanceOf<TestStateV5>());
|
||||
Assert.That(receivedEvent.NewState, Is.InstanceOf<TestStateV5_2>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试异步切换时多次状态变更都能正确触发事件
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_MultipleChanges_Should_Send_Events_Correctly()
|
||||
{
|
||||
var eventCount = 0;
|
||||
|
||||
_eventBus!.Register<StateChangedEvent>(_ => { eventCount++; });
|
||||
|
||||
var state1 = new TestStateV5();
|
||||
var state2 = new TestStateV5_2();
|
||||
|
||||
_stateMachine!.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
_stateMachine.Init();
|
||||
await _stateMachine.ChangeToAsync<TestStateV5>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV5_2>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV5>();
|
||||
|
||||
Assert.That(eventCount, Is.EqualTo(3));
|
||||
}
|
||||
}
|
||||
|
||||
#region Test Classes
|
||||
@ -370,4 +457,41 @@ public class TestStateV5 : IState
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 第二个测试用的普通状态实现,用于区分不同状态类型
|
||||
/// </summary>
|
||||
public class TestStateV5_2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态标识符
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否可以转换到指定状态
|
||||
/// </summary>
|
||||
/// <param name="next">目标状态</param>
|
||||
/// <returns>始终返回true表示允许转换</returns>
|
||||
public bool CanTransitionTo(IState next)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时调用
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态</param>
|
||||
public void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态</param>
|
||||
public void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -241,6 +241,394 @@ public class StateMachineTests
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(state1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步注销后状态应从字典中移除
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UnregisterAsync_Should_RemoveState_FromDictionary()
|
||||
{
|
||||
var state = new TestStateV2();
|
||||
_stateMachine.Register(state);
|
||||
await _stateMachine.UnregisterAsync<TestStateV2>();
|
||||
|
||||
Assert.That(_stateMachine.ContainsState<TestStateV2>(), Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步注销活动同步状态时调用OnExit
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UnregisterAsync_WhenStateIsActive_WithSyncState_Should_Invoke_OnExit()
|
||||
{
|
||||
var state = new TestStateV2();
|
||||
_stateMachine.Register(state);
|
||||
_stateMachine.ChangeTo<TestStateV2>();
|
||||
await _stateMachine.UnregisterAsync<TestStateV2>();
|
||||
|
||||
Assert.That(state.ExitCalled, Is.True);
|
||||
Assert.That(state.ExitTo, Is.Null);
|
||||
Assert.That(_stateMachine.Current, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步注销活动异步状态时调用OnExitAsync
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UnregisterAsync_WhenStateIsActive_WithAsyncState_Should_Invoke_OnExitAsync()
|
||||
{
|
||||
var state = new TestAsyncState();
|
||||
_stateMachine.Register(state);
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
await _stateMachine.UnregisterAsync<TestAsyncState>();
|
||||
|
||||
Assert.That(state.ExitCalled, Is.True);
|
||||
Assert.That(state.ExitTo, Is.Null);
|
||||
Assert.That(_stateMachine.Current, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步注销非活动状态不调用退出方法
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task UnregisterAsync_WhenStateNotActive_Should_Not_Invoke_Exit()
|
||||
{
|
||||
var state1 = new TestStateV2();
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
_stateMachine.ChangeTo<TestStateV2>();
|
||||
|
||||
await _stateMachine.UnregisterAsync<TestStateV3>();
|
||||
|
||||
Assert.That(state1.ExitCalled, Is.False);
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(state1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步切换检查未注册状态返回false
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanChangeToAsync_WhenStateNotRegistered_Should_ReturnFalse()
|
||||
{
|
||||
var result = await _stateMachine.CanChangeToAsync<TestStateV2>();
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步切换检查已注册状态返回true
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanChangeToAsync_WhenStateRegistered_Should_ReturnTrue()
|
||||
{
|
||||
var state = new TestStateV2();
|
||||
_stateMachine.Register(state);
|
||||
|
||||
var result = await _stateMachine.CanChangeToAsync<TestStateV2>();
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步切换检查当前状态拒绝转换时返回false
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanChangeToAsync_WhenCurrentStateDeniesTransition_Should_ReturnFalse()
|
||||
{
|
||||
var state1 = new TestStateV2 { AllowTransition = false };
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
_stateMachine.ChangeTo<TestStateV2>();
|
||||
|
||||
var result = await _stateMachine.CanChangeToAsync<TestStateV3>();
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步切换检查使用异步状态时调用CanTransitionToAsync
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanChangeToAsync_WithAsyncState_Should_Call_CanTransitionToAsync()
|
||||
{
|
||||
var state1 = new TestAsyncState();
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
|
||||
await _stateMachine.CanChangeToAsync<TestStateV3>();
|
||||
Assert.That(state1.CanTransitionToCallCount, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步切换检查使用同步状态时调用CanTransitionTo
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanChangeToAsync_WithSyncState_Should_Call_CanTransitionTo()
|
||||
{
|
||||
var state1 = new TestStateV2 { AllowTransition = false };
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
_stateMachine.ChangeTo<TestStateV2>();
|
||||
|
||||
var result = await _stateMachine.CanChangeToAsync<TestStateV3>();
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换能够正确设置当前状态
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_Should_SetCurrentState()
|
||||
{
|
||||
var state = new TestStateV2();
|
||||
_stateMachine.Register(state);
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(state));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换对于异步状态调用OnEnterAsync
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_Should_Invoke_OnEnterAsync_ForAsyncState()
|
||||
{
|
||||
var state = new TestAsyncState();
|
||||
_stateMachine.Register(state);
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
|
||||
Assert.That(state.EnterCalled, Is.True);
|
||||
Assert.That(state.EnterFrom, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换对于同步状态调用OnEnter
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_Should_Invoke_OnEnter_ForSyncState()
|
||||
{
|
||||
var state = new TestStateV2();
|
||||
_stateMachine.Register(state);
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
|
||||
Assert.That(state.EnterCalled, Is.True);
|
||||
Assert.That(state.EnterFrom, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换当存在当前异步状态时调用OnExitAsync
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_When_CurrentStateExists_WithAsyncState_Should_Invoke_OnExitAsync()
|
||||
{
|
||||
var state1 = new TestAsyncState();
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV3>();
|
||||
|
||||
Assert.That(state1.ExitCalled, Is.True);
|
||||
Assert.That(state1.ExitTo, Is.SameAs(state2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换当存在当前同步状态时调用OnExit
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_When_CurrentStateExists_WithSyncState_Should_Invoke_OnExit()
|
||||
{
|
||||
var state1 = new TestStateV2();
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV3>();
|
||||
|
||||
Assert.That(state1.ExitCalled, Is.True);
|
||||
Assert.That(state1.ExitTo, Is.SameAs(state2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换到相同状态时不应调用回调方法
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_ToSameState_Should_NotInvoke_Callbacks()
|
||||
{
|
||||
var state = new TestStateV2();
|
||||
_stateMachine.Register(state);
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
|
||||
var enterCount = state.EnterCallCount;
|
||||
var exitCount = state.ExitCallCount;
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
|
||||
Assert.That(state.EnterCallCount, Is.EqualTo(enterCount));
|
||||
Assert.That(state.ExitCallCount, Is.EqualTo(exitCount));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换到未注册状态时应抛出InvalidOperationException
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ChangeToAsync_ToUnregisteredState_Should_ThrowInvalidOperationException()
|
||||
{
|
||||
Assert.ThrowsAsync<InvalidOperationException>(async () => await _stateMachine.ChangeToAsync<TestStateV2>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换当当前状态拒绝转换时不应发生状态变化
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_WhenCurrentStateDeniesTransition_Should_NotChange()
|
||||
{
|
||||
var state1 = new TestStateV2 { AllowTransition = false };
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
|
||||
var oldState = _stateMachine.Current;
|
||||
var result = await _stateMachine.ChangeToAsync<TestStateV3>();
|
||||
|
||||
Assert.That(result, Is.False);
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(oldState));
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(state1));
|
||||
Assert.That(state2.EnterCalled, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态切换当当前异步状态拒绝转换时调用CanTransitionToAsync
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_WhenCurrentStateDeniesTransition_WithAsyncState_Should_Call_CanTransitionToAsync()
|
||||
{
|
||||
var state1 = new TestAsyncState { AllowTransition = false };
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestStateV3>();
|
||||
|
||||
Assert.That(state1.CanTransitionToCallCount, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步回退能够返回到上一个状态
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GoBackAsync_Should_ReturnTo_PreviousState()
|
||||
{
|
||||
var state1 = new TestStateV2();
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV3>();
|
||||
var result = await _stateMachine.GoBackAsync();
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(state1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步回退当没有历史记录时返回false
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GoBackAsync_WhenNoHistory_Should_ReturnFalse()
|
||||
{
|
||||
var result = await _stateMachine.GoBackAsync();
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步回退调用正确的状态转换方法
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GoBackAsync_Should_Invoke_Correct_Transition_Methods()
|
||||
{
|
||||
var state1 = new TestAsyncState();
|
||||
var state2 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV3>();
|
||||
await _stateMachine.GoBackAsync();
|
||||
|
||||
Assert.That(state2.ExitCalled, Is.True);
|
||||
Assert.That(state1.EnterCallCount, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证从同步状态切换到异步状态能够正常工作
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_FromSyncToAsyncState_Should_Work()
|
||||
{
|
||||
var state1 = new TestStateV2();
|
||||
var state2 = new TestAsyncState();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
|
||||
Assert.That(state1.ExitCalled, Is.True);
|
||||
Assert.That(state2.EnterCalled, Is.True);
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(state2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证从异步状态切换到同步状态能够正常工作
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeToAsync_FromAsyncToSyncState_Should_Work()
|
||||
{
|
||||
var state1 = new TestAsyncState();
|
||||
var state2 = new TestStateV2();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
|
||||
Assert.That(state1.ExitCalled, Is.True);
|
||||
Assert.That(state2.EnterCalled, Is.True);
|
||||
Assert.That(_stateMachine.Current, Is.SameAs(state2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证多次异步状态转换应正确调用回调方法
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task MultipleAsyncStateChanges_Should_Invoke_Callbacks_Correctly()
|
||||
{
|
||||
var state1 = new TestAsyncState();
|
||||
var state2 = new TestStateV2();
|
||||
var state3 = new TestStateV3();
|
||||
_stateMachine.Register(state1);
|
||||
_stateMachine.Register(state2);
|
||||
_stateMachine.Register(state3);
|
||||
|
||||
await _stateMachine.ChangeToAsync<TestAsyncState>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV2>();
|
||||
await _stateMachine.ChangeToAsync<TestStateV3>();
|
||||
|
||||
Assert.That(state1.EnterCalled, Is.True);
|
||||
Assert.That(state1.ExitCalled, Is.True);
|
||||
Assert.That(state2.EnterCalled, Is.True);
|
||||
Assert.That(state2.ExitCalled, Is.True);
|
||||
Assert.That(state3.EnterCalled, Is.True);
|
||||
Assert.That(state3.ExitCalled, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证多次状态转换应正确调用回调方法
|
||||
/// </summary>
|
||||
@ -424,6 +812,85 @@ public sealed class TestStateV4 : IState
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步测试状态类,同时实现IState和IAsyncState接口用于测试异步状态功能
|
||||
/// </summary>
|
||||
public sealed class TestAsyncState : IState, IAsyncState
|
||||
{
|
||||
public bool AllowTransition { get; set; } = true;
|
||||
public bool EnterCalled { get; private set; }
|
||||
public bool ExitCalled { get; private set; }
|
||||
public int EnterCallCount { get; private set; }
|
||||
public int ExitCallCount { get; private set; }
|
||||
public IState? EnterFrom { get; private set; }
|
||||
public IState? ExitTo { get; private set; }
|
||||
public int CanTransitionToCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步进入状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public async Task OnEnterAsync(IState? from)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步离开状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="to">离开到哪个状态</param>
|
||||
public async Task OnExitAsync(IState? to)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>是否允许转换</returns>
|
||||
public async Task<bool> CanTransitionToAsync(IState target)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
CanTransitionToCallCount++;
|
||||
return AllowTransition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时的回调方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnEnter should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开状态时的回调方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="to">离开到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnExit should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>是否允许转换</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态机扩展方法类
|
||||
/// </summary>
|
||||
|
||||
@ -194,6 +194,137 @@ public class StateTests
|
||||
Assert.That(state2.EnterFrom, Is.SameAs(state1));
|
||||
Assert.That(state3.EnterFrom, Is.SameAs(state2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态类是否正确实现了IAsyncState接口
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AsyncState_Should_Implement_IAsyncState_Interface()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2();
|
||||
|
||||
Assert.That(state is IAsyncState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证进入异步状态时OnEnterAsync方法被正确调用并记录来源状态
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnEnterAsync_Should_BeCalled_When_AsyncState_Enters()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2();
|
||||
var otherState = new ConcreteStateV3();
|
||||
|
||||
await state.OnEnterAsync(otherState);
|
||||
|
||||
Assert.That(state.EnterCalled, Is.True);
|
||||
Assert.That(state.EnterFrom, Is.SameAs(otherState));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证当传入null作为来源状态时异步状态的处理情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnEnterAsync_WithNull_Should_Set_EnterFrom_ToNull()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2();
|
||||
|
||||
await state.OnEnterAsync(null);
|
||||
|
||||
Assert.That(state.EnterCalled, Is.True);
|
||||
Assert.That(state.EnterFrom, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证退出异步状态时OnExitAsync方法被正确调用并记录目标状态
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnExitAsync_Should_BeCalled_When_AsyncState_Exits()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2();
|
||||
var otherState = new ConcreteStateV3();
|
||||
|
||||
await state.OnExitAsync(otherState);
|
||||
|
||||
Assert.That(state.ExitCalled, Is.True);
|
||||
Assert.That(state.ExitTo, Is.SameAs(otherState));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证当传入null作为目标状态时异步状态的处理情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnExitAsync_WithNull_Should_Set_ExitTo_ToNull()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2();
|
||||
|
||||
await state.OnExitAsync(null);
|
||||
|
||||
Assert.That(state.ExitCalled, Is.True);
|
||||
Assert.That(state.ExitTo, Is.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证允许转换时CanTransitionToAsync方法返回true
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanTransitionToAsync_WithAllowTrue_Should_ReturnTrue()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2 { AllowTransitions = true };
|
||||
var target = new ConcreteStateV3();
|
||||
|
||||
var result = await state.CanTransitionToAsync(target);
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证不允许转换时CanTransitionToAsync方法返回false
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanTransitionToAsync_WithAllowFalse_Should_ReturnFalse()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2 { AllowTransitions = false };
|
||||
var target = new ConcreteStateV3();
|
||||
|
||||
var result = await state.CanTransitionToAsync(target);
|
||||
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证CanTransitionToAsync方法正确接收目标状态参数
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task CanTransitionToAsync_Should_Receive_TargetState()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2 { AllowTransitions = true };
|
||||
var target = new ConcreteStateV3();
|
||||
IState? receivedTarget = null;
|
||||
|
||||
state.CanTransitionToAsyncAction = s => receivedTarget = s;
|
||||
await state.CanTransitionToAsync(target);
|
||||
|
||||
Assert.That(receivedTarget, Is.SameAs(target));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证异步状态对多次转换的跟踪能力
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task AsyncState_Should_Track_MultipleTransitions()
|
||||
{
|
||||
var state = new ConcreteAsyncStateV2();
|
||||
var other = new ConcreteStateV3();
|
||||
|
||||
await state.OnEnterAsync(other);
|
||||
await state.OnExitAsync(other);
|
||||
await state.OnEnterAsync(other);
|
||||
await state.OnExitAsync(null);
|
||||
|
||||
Assert.That(state.EnterCallCount, Is.EqualTo(2));
|
||||
Assert.That(state.ExitCallCount, Is.EqualTo(2));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -490,4 +621,114 @@ public sealed class TrackingStateV2 : IState
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步具体状态实现类V2版本,用于测试异步状态的基本功能
|
||||
/// </summary>
|
||||
public sealed class ConcreteAsyncStateV2 : IState, IAsyncState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许转换
|
||||
/// </summary>
|
||||
public bool AllowTransitions { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态被调用的次数
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态被调用的次数
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置转换到目标状态时执行的动作
|
||||
/// </summary>
|
||||
public Action<IState>? CanTransitionToAsyncAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步进入当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public async Task OnEnterAsync(IState? from)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步退出当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public async Task OnExitAsync(IState? to)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果可以转换则返回true,否则返回false</returns>
|
||||
public async Task<bool> CanTransitionToAsync(IState target)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
CanTransitionToAsyncAction?.Invoke(target);
|
||||
return AllowTransitions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnEnter should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnExit should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果可以转换则返回true,否则返回false</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state");
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ using GFramework.Core.Abstractions.query;
|
||||
using GFramework.Core.Abstractions.rule;
|
||||
using GFramework.Core.Abstractions.system;
|
||||
using GFramework.Core.Abstractions.utility;
|
||||
using Mediator;
|
||||
|
||||
namespace GFramework.Core.extensions;
|
||||
|
||||
@ -19,7 +20,7 @@ public static class ContextAwareExtensions
|
||||
/// </summary>
|
||||
/// <typeparam name="TService">要获取的服务类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的上下文感知对象</param>
|
||||
/// <returns>指定类型的服务实例,如果未找到则返回 null</returns>
|
||||
/// <returns>指定类型的服务实例,如果未找到则返回 null</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 参数为 null 时抛出</exception>
|
||||
public static TService? GetService<TService>(this IContextAware contextAware) where TService : class
|
||||
{
|
||||
@ -71,56 +72,6 @@ public static class ContextAwareExtensions
|
||||
return context.GetUtility<TUtility>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送一个查询请求
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">查询结果类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="query">要发送的查询</param>
|
||||
/// <returns>查询结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 query 为 null 时抛出</exception>
|
||||
public static TResult SendQuery<TResult>(this IContextAware contextAware, IQuery<TResult> query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendQuery(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送并异步执行一个无返回值的命令
|
||||
/// </summary>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static async Task SendCommandAsync(this IContextAware contextAware, IAsyncCommand command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
await context.SendCommandAsync(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送并异步执行一个带返回值的命令
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">命令执行结果类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <returns>命令执行结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static async Task<TResult> SendCommandAsync<TResult>(this IContextAware contextAware,
|
||||
IAsyncCommand<TResult> command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return await context.SendCommandAsync(command);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 发送一个事件
|
||||
@ -151,39 +102,6 @@ public static class ContextAwareExtensions
|
||||
context.SendEvent(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送一个事件
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">命令执行结果类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <returns>命令执行结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static TResult SendCommand<TResult>(this IContextAware contextAware, ICommand<TResult> command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendCommand(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送一个无返回结果的命令
|
||||
/// </summary>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static void SendCommand(this IContextAware contextAware, ICommand command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
context.SendCommand(command);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 注册事件处理器
|
||||
/// </summary>
|
||||
@ -222,7 +140,7 @@ public static class ContextAwareExtensions
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要获取的环境对象类型</typeparam>
|
||||
/// <param name="contextAware">上下文感知对象</param>
|
||||
/// <returns>指定类型的环境对象,如果无法转换则返回null</returns>
|
||||
/// <returns>指定类型的环境对象,如果无法转换则返回null</returns>
|
||||
public static T? GetEnvironment<T>(this IContextAware contextAware) where T : class
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
@ -243,4 +161,338 @@ public static class ContextAwareExtensions
|
||||
var context = contextAware.GetContext();
|
||||
return context.GetEnvironment();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// [Mediator] 发送命令的同步版本(不推荐,仅用于兼容性)
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">命令响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令对象</param>
|
||||
/// <returns>命令执行结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static TResponse SendCommand<TResponse>(this IContextAware contextAware,
|
||||
Mediator.ICommand<TResponse> command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendCommand(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送一个带返回结果的命令
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">命令执行结果类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <returns>命令执行结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static TResult SendCommand<TResult>(this IContextAware contextAware,
|
||||
Abstractions.command.ICommand<TResult> command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendCommand(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送一个无返回结果的命令
|
||||
/// </summary>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static void SendCommand(this IContextAware contextAware, Abstractions.command.ICommand command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
context.SendCommand(command);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// [Mediator] 异步发送命令并返回结果
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">命令响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令对象</param>
|
||||
/// <param name="cancellationToken">取消令牌,用于取消操作</param>
|
||||
/// <returns>包含命令执行结果的ValueTask</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static ValueTask<TResponse> SendCommandAsync<TResponse>(this IContextAware contextAware,
|
||||
Mediator.ICommand<TResponse> command, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendCommandAsync(command, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送并异步执行一个无返回值的命令
|
||||
/// </summary>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static async Task SendCommandAsync(this IContextAware contextAware, IAsyncCommand command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
await context.SendCommandAsync(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送并异步执行一个带返回值的命令
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">命令执行结果类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <returns>命令执行结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static async Task<TResult> SendCommandAsync<TResult>(this IContextAware contextAware,
|
||||
IAsyncCommand<TResult> command)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return await context.SendCommandAsync(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [Mediator] 发送查询的同步版本(不推荐,仅用于兼容性)
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">查询响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="query">要发送的查询对象</param>
|
||||
/// <returns>查询结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 query 为 null 时抛出</exception>
|
||||
public static TResponse SendQuery<TResponse>(this IContextAware contextAware, Mediator.IQuery<TResponse> query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendQuery(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送一个查询请求
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">查询结果类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="query">要发送的查询</param>
|
||||
/// <returns>查询结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 query 为 null 时抛出</exception>
|
||||
public static TResult SendQuery<TResult>(this IContextAware contextAware, Abstractions.query.IQuery<TResult> query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendQuery(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [Mediator] 异步发送查询并返回结果
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">查询响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="query">要发送的查询对象</param>
|
||||
/// <param name="cancellationToken">取消令牌,用于取消操作</param>
|
||||
/// <returns>包含查询结果的ValueTask</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 query 为 null 时抛出</exception>
|
||||
public static ValueTask<TResponse> SendQueryAsync<TResponse>(this IContextAware contextAware,
|
||||
Mediator.IQuery<TResponse> query, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendQueryAsync(query, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步发送一个查询请求
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">查询结果类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="query">要发送的异步查询</param>
|
||||
/// <returns>查询结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 query 为 null 时抛出</exception>
|
||||
public static async Task<TResult> SendQueryAsync<TResult>(this IContextAware contextAware,
|
||||
IAsyncQuery<TResult> query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return await context.SendQueryAsync(query);
|
||||
}
|
||||
|
||||
// === 统一请求处理方法 ===
|
||||
|
||||
/// <summary>
|
||||
/// 发送请求(统一处理 Command/Query)
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="request">要发送的请求</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>请求结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 request 为 null 时抛出</exception>
|
||||
public static ValueTask<TResponse> SendRequestAsync<TResponse>(this IContextAware contextAware,
|
||||
IRequest<TResponse> request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendRequestAsync(request, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送请求(同步版本,不推荐)
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="request">要发送的请求</param>
|
||||
/// <returns>请求结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 request 为 null 时抛出</exception>
|
||||
public static TResponse SendRequest<TResponse>(this IContextAware contextAware,
|
||||
IRequest<TResponse> request)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendRequest(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布通知(一对多事件)
|
||||
/// </summary>
|
||||
/// <typeparam name="TNotification">通知类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="notification">要发布的通知</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>异步任务</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 notification 为 null 时抛出</exception>
|
||||
public static ValueTask PublishAsync<TNotification>(this IContextAware contextAware,
|
||||
TNotification notification, CancellationToken cancellationToken = default)
|
||||
where TNotification : INotification
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(notification);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.PublishAsync(notification, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建流式请求(用于大数据集)
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="request">流式请求</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>异步响应流</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 request 为 null 时抛出</exception>
|
||||
public static IAsyncEnumerable<TResponse> CreateStream<TResponse>(this IContextAware contextAware,
|
||||
IStreamRequest<TResponse> request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.CreateStream(request, cancellationToken);
|
||||
}
|
||||
|
||||
// === 便捷扩展方法 ===
|
||||
|
||||
/// <summary>
|
||||
/// 发送命令(无返回值)
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand">命令类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>异步任务</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static ValueTask SendAsync<TCommand>(this IContextAware contextAware, TCommand command,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TCommand : IRequest<Unit>
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendAsync(command, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送命令(有返回值)
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>命令执行结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||
public static ValueTask<TResponse> SendAsync<TResponse>(this IContextAware contextAware,
|
||||
IRequest<TResponse> command, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.SendAsync(command, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送查询
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">响应类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="query">要发送的查询</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>查询结果</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 query 为 null 时抛出</exception>
|
||||
public static ValueTask<TResponse> QueryAsync<TResponse>(this IContextAware contextAware,
|
||||
IRequest<TResponse> query, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.QueryAsync(query, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布事件通知
|
||||
/// </summary>
|
||||
/// <typeparam name="TNotification">通知类型</typeparam>
|
||||
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||
/// <param name="notification">要发布的通知</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>异步任务</returns>
|
||||
/// <exception cref="ArgumentNullException">当 contextAware 或 notification 为 null 时抛出</exception>
|
||||
public static ValueTask PublishEventAsync<TNotification>(this IContextAware contextAware,
|
||||
TNotification notification, CancellationToken cancellationToken = default)
|
||||
where TNotification : INotification
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(contextAware);
|
||||
ArgumentNullException.ThrowIfNull(notification);
|
||||
|
||||
var context = contextAware.GetContext();
|
||||
return context.PublishEventAsync(notification, cancellationToken);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
using GFramework.Core.Abstractions.architecture;
|
||||
using GFramework.Core.Abstractions.architecture;
|
||||
using GFramework.Core.Abstractions.enums;
|
||||
using GFramework.Core.Abstractions.rule;
|
||||
using GFramework.Core.Abstractions.state;
|
||||
@ -87,4 +87,21 @@ public class StateMachineSystem : StateMachine, IStateMachineSystem
|
||||
NewState = Current
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步内部状态切换方法,重写基类方法以添加状态变更事件通知功能
|
||||
/// </summary>
|
||||
/// <param name="next">要切换到的下一个状态</param>
|
||||
protected override async Task ChangeInternalAsync(IState next)
|
||||
{
|
||||
var old = Current;
|
||||
await base.ChangeInternalAsync(next);
|
||||
|
||||
// 发送状态变更事件,通知监听者状态已发生改变
|
||||
this.SendEvent(new StateChangedEvent
|
||||
{
|
||||
OldState = old,
|
||||
NewState = Current
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user