Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ jobs:
--logger "trx;LogFileName=sg-$RANDOM.trx" \
--results-directory TestResults &

dotnet test GFramework.Cqrs.Tests \
-c Release \
--no-build \
--logger "trx;LogFileName=cqrs-$RANDOM.trx" \
--results-directory TestResults &

dotnet test GFramework.Ecs.Arch.Tests \
-c Release \
--no-build \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Events;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Query;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Cqrs.Abstractions.Cqrs;
using ICommand = GFramework.Core.Abstractions.Command.ICommand;

namespace GFramework.Core.Abstractions.Architectures;
Expand Down Expand Up @@ -131,7 +131,7 @@ public interface IArchitectureContext
/// <remarks>
/// 这是迁移后的推荐命令入口。无返回值命令应实现 <c>IRequest&lt;Unit&gt;</c>,并优先通过 <see cref="SendAsync{TCommand}(TCommand,CancellationToken)" /> 调用。
/// </remarks>
TResponse SendCommand<TResponse>(Cqrs.Command.ICommand<TResponse> command);
TResponse SendCommand<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command);


/// <summary>
Expand All @@ -147,7 +147,8 @@ public interface IArchitectureContext
/// <param name="command">要发送的 CQRS 命令。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>包含命令执行结果的值任务。</returns>
ValueTask<TResponse> SendCommandAsync<TResponse>(Cqrs.Command.ICommand<TResponse> command,
ValueTask<TResponse> SendCommandAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command,
CancellationToken cancellationToken = default);


Expand Down Expand Up @@ -176,7 +177,7 @@ ValueTask<TResponse> SendCommandAsync<TResponse>(Cqrs.Command.ICommand<TResponse
/// <remarks>
/// 这是迁移后的推荐查询入口。新查询应优先实现 <c>GFramework.Core.Abstractions.Cqrs.Query.IQuery&lt;TResponse&gt;</c>。
/// </remarks>
TResponse SendQuery<TResponse>(Cqrs.Query.IQuery<TResponse> query);
TResponse SendQuery<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query);

/// <summary>
/// 异步发送一个旧版查询请求。
Expand All @@ -193,7 +194,7 @@ ValueTask<TResponse> SendCommandAsync<TResponse>(Cqrs.Command.ICommand<TResponse
/// <param name="query">要发送的 CQRS 查询。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>包含查询结果的值任务。</returns>
ValueTask<TResponse> SendQueryAsync<TResponse>(Cqrs.Query.IQuery<TResponse> query,
ValueTask<TResponse> SendQueryAsync<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query,
CancellationToken cancellationToken = default);

/// <summary>
Expand Down
52 changes: 52 additions & 0 deletions GFramework.Core.Abstractions/Cqrs/ICqrsRuntime.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using GFramework.Core.Abstractions.Architectures;
using GFramework.Cqrs.Abstractions.Cqrs;

namespace GFramework.Core.Abstractions.Cqrs;

/// <summary>
/// 定义架构上下文使用的 CQRS runtime seam。
/// 该抽象把请求分发、通知发布与流式处理从具体实现中解耦,
/// 使 <see cref="IArchitectureContext" /> 不再直接依赖某个固定的 runtime 类型。
/// </summary>
public interface ICqrsRuntime
{
/// <summary>
/// 发送请求并返回响应。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="context">当前架构上下文,用于上下文感知处理器注入与嵌套请求访问。</param>
/// <param name="request">要分发的请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>请求响应。</returns>
ValueTask<TResponse> SendAsync<TResponse>(
IArchitectureContext context,
IRequest<TResponse> request,
CancellationToken cancellationToken = default);

/// <summary>
/// 发布通知到所有已注册处理器。
/// </summary>
/// <typeparam name="TNotification">通知类型。</typeparam>
/// <param name="context">当前架构上下文,用于上下文感知处理器注入。</param>
/// <param name="notification">要发布的通知。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>表示通知分发完成的值任务。</returns>
ValueTask PublishAsync<TNotification>(
IArchitectureContext context,
TNotification notification,
CancellationToken cancellationToken = default)
where TNotification : INotification;

/// <summary>
/// 创建流式请求的异步响应序列。
/// </summary>
/// <typeparam name="TResponse">流元素类型。</typeparam>
/// <param name="context">当前架构上下文,用于上下文感知处理器注入。</param>
/// <param name="request">流式请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>按需生成的异步响应序列。</returns>
IAsyncEnumerable<TResponse> CreateStream<TResponse>(
IArchitectureContext context,
IStreamRequest<TResponse> request,
CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
<ItemGroup>
<Using Include="GFramework.Core.Abstractions"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GFramework.Cqrs.Abstractions\GFramework.Cqrs.Abstractions.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Update="Meziantou.Analyzer" Version="3.0.46">
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Architectures;
using GFramework.Core.Logging;
using GFramework.Cqrs.Abstractions.Cqrs;

namespace GFramework.Core.Tests.Architectures;

Expand All @@ -12,8 +13,6 @@ namespace GFramework.Core.Tests.Architectures;
[TestFixture]
public sealed class ArchitectureAdditionalCqrsHandlersTests
{
private ILoggerFactoryProvider? _previousLoggerFactoryProvider;

/// <summary>
/// 初始化日志工厂和共享测试状态。
/// </summary>
Expand All @@ -39,6 +38,8 @@ public void TearDown()
"LoggerFactoryResolver.Provider should be captured during setup.");
}

private ILoggerFactoryProvider? _previousLoggerFactoryProvider;

/// <summary>
/// 验证显式声明的额外程序集会在初始化阶段接入当前架构容器。
/// </summary>
Expand Down Expand Up @@ -197,4 +198,4 @@ private static INotificationHandler<AdditionalAssemblyNotification> CreateHandle
});
return handler.Object;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Architectures;
using GFramework.Core.Logging;
using GfCqrs = GFramework.Core.Abstractions.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs;

namespace GFramework.Core.Tests.Architectures;

Expand Down Expand Up @@ -151,14 +151,14 @@ private sealed class InstalledByModuleUtility : IUtility
/// <summary>
/// 用于验证管道行为注册是否生效的测试请求。
/// </summary>
public sealed class ModuleBehaviorRequest : GfCqrs.IRequest<string>
public sealed class ModuleBehaviorRequest : IRequest<string>
{
}

/// <summary>
/// 处理测试请求的处理器。
/// </summary>
public sealed class ModuleBehaviorRequestHandler : GfCqrs.IRequestHandler<ModuleBehaviorRequest, string>
public sealed class ModuleBehaviorRequestHandler : IRequestHandler<ModuleBehaviorRequest, string>
{
/// <summary>
/// 返回固定结果,便于聚焦验证管道行为是否执行。
Expand All @@ -177,8 +177,8 @@ public ValueTask<string> Handle(ModuleBehaviorRequest request, CancellationToken
/// </summary>
/// <typeparam name="TRequest">请求类型。</typeparam>
/// <typeparam name="TResponse">响应类型。</typeparam>
public sealed class TrackingPipelineBehavior<TRequest, TResponse> : GfCqrs.IPipelineBehavior<TRequest, TResponse>
where TRequest : GfCqrs.IRequest<TResponse>
public sealed class TrackingPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
/// <summary>
/// 获取当前测试进程中该请求类型对应的行为触发次数。
Expand All @@ -193,7 +193,7 @@ public sealed class TrackingPipelineBehavior<TRequest, TResponse> : GfCqrs.IPipe
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>下游处理器的响应结果。</returns>
public async ValueTask<TResponse> Handle(
TRequest message, GfCqrs.MessageHandlerDelegate<TRequest, TResponse> next,
TRequest message, MessageHandlerDelegate<TRequest, TResponse> next,
CancellationToken cancellationToken)
{
InvocationCount++;
Expand Down
20 changes: 11 additions & 9 deletions GFramework.Core.Tests/Architectures/ArchitectureServicesTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Events;
using GFramework.Core.Abstractions.Ioc;
Expand All @@ -14,6 +13,7 @@
using GFramework.Core.Events;
using GFramework.Core.Ioc;
using GFramework.Core.Query;
using GFramework.Cqrs.Abstractions.Cqrs;
using ICommand = GFramework.Core.Abstractions.Command.ICommand;

namespace GFramework.Core.Tests.Architectures;
Expand All @@ -34,17 +34,17 @@ namespace GFramework.Core.Tests.Architectures;
[TestFixture]
public class ArchitectureServicesTests
{
private TestArchitectureContextV3? _context;

private ArchitectureServices? _services;

[SetUp]
public void SetUp()
{
_services = new ArchitectureServices();
_context = new TestArchitectureContextV3();
}

private TestArchitectureContextV3? _context;

private ArchitectureServices? _services;

private void RegisterBuiltInServices()
{
_services!.ModuleManager.RegisterBuiltInModules(_services.Container);
Expand Down Expand Up @@ -359,24 +359,26 @@ public TResponse SendRequest<TResponse>(IRequest<TResponse> request)
throw new NotImplementedException();
}

public ValueTask<TResponse> SendCommandAsync<TResponse>(Abstractions.Cqrs.Command.ICommand<TResponse> command,
public ValueTask<TResponse> SendCommandAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}

public TResponse SendCommand<TResponse>(Abstractions.Cqrs.Command.ICommand<TResponse> command)
public TResponse SendCommand<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command)
{
throw new NotImplementedException();
}

public ValueTask<TResponse> SendQueryAsync<TResponse>(Abstractions.Cqrs.Query.IQuery<TResponse> query,
public ValueTask<TResponse> SendQueryAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query,
CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}

public TResponse SendQuery<TResponse>(Abstractions.Cqrs.Query.IQuery<TResponse> query)
public TResponse SendQuery<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query)
{
throw new NotImplementedException();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Expand Down
12 changes: 7 additions & 5 deletions GFramework.Core.Tests/Architectures/GameContextTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Events;
using GFramework.Core.Abstractions.Ioc;
Expand All @@ -14,6 +13,7 @@
using GFramework.Core.Events;
using GFramework.Core.Ioc;
using GFramework.Core.Query;
using GFramework.Cqrs.Abstractions.Cqrs;
using ICommand = GFramework.Core.Abstractions.Command.ICommand;

namespace GFramework.Core.Tests.Architectures;
Expand Down Expand Up @@ -428,7 +428,8 @@ public TResponse SendRequest<TResponse>(IRequest<TResponse> request)
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>命令响应任务。</returns>
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
public ValueTask<TResponse> SendCommandAsync<TResponse>(Abstractions.Cqrs.Command.ICommand<TResponse> command,
public ValueTask<TResponse> SendCommandAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
Expand All @@ -441,7 +442,7 @@ public ValueTask<TResponse> SendCommandAsync<TResponse>(Abstractions.Cqrs.Comman
/// <param name="command">要发送的命令。</param>
/// <returns>命令响应。</returns>
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
public TResponse SendCommand<TResponse>(Abstractions.Cqrs.Command.ICommand<TResponse> command)
public TResponse SendCommand<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command)
{
throw new NotImplementedException();
}
Expand All @@ -454,7 +455,8 @@ public TResponse SendCommand<TResponse>(Abstractions.Cqrs.Command.ICommand<TResp
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>查询结果任务。</returns>
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
public ValueTask<TResponse> SendQueryAsync<TResponse>(Abstractions.Cqrs.Query.IQuery<TResponse> query,
public ValueTask<TResponse> SendQueryAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query,
CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
Expand All @@ -467,7 +469,7 @@ public ValueTask<TResponse> SendQueryAsync<TResponse>(Abstractions.Cqrs.Query.IQ
/// <param name="query">要发送的查询。</param>
/// <returns>查询结果。</returns>
/// <exception cref="NotImplementedException">该测试桩未实现此成员。</exception>
public TResponse SendQuery<TResponse>(Abstractions.Cqrs.Query.IQuery<TResponse> query)
public TResponse SendQuery<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query)
{
throw new NotImplementedException();
}
Expand Down
4 changes: 2 additions & 2 deletions GFramework.Core.Tests/Command/AbstractAsyncCommandTests.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Cqrs.Command;
using GFramework.Core.Abstractions.Rule;
using GFramework.Core.Architectures;
using GFramework.Core.Command;
using GFramework.Core.Environment;
using GFramework.Core.Events;
using GFramework.Core.Ioc;
using GFramework.Core.Query;
using GFramework.Cqrs.Abstractions.Cqrs.Command;

namespace GFramework.Core.Tests.Command;

Expand Down Expand Up @@ -396,4 +396,4 @@ protected override Task<int> OnExecuteAsync(TestCommandInputV2 input)
Executed = true;
return Task.FromResult(input.Value * 3);
}
}
}
4 changes: 2 additions & 2 deletions GFramework.Core.Tests/Command/CommandExecutorTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using GFramework.Core.Abstractions.Cqrs.Command;
using GFramework.Core.Command;
using GFramework.Cqrs.Abstractions.Cqrs.Command;

namespace GFramework.Core.Tests.Command;

Expand Down Expand Up @@ -261,4 +261,4 @@ protected override Task<int> OnExecuteAsync(TestCommandInput input)
Executed = true;
return Task.FromResult(input.Value * 2);
}
}
}
38 changes: 38 additions & 0 deletions GFramework.Core.Tests/Cqrs/ContainerRegistrationFixtures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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.Cqrs.Abstractions.Cqrs;

namespace GFramework.Core.Tests.Cqrs;

/// <summary>
/// 为容器层测试提供可扫描的最小通知夹具。
/// </summary>
internal sealed record DeterministicOrderNotification : INotification;

/// <summary>
/// 供容器注册测试验证程序集扫描结果的通知处理器。
/// </summary>
internal sealed class DeterministicOrderNotificationHandler : INotificationHandler<DeterministicOrderNotification>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
{
/// <summary>
/// 无副作用地消费通知。
/// </summary>
/// <param name="notification">通知实例。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>已完成任务。</returns>
public ValueTask Handle(DeterministicOrderNotification notification, CancellationToken cancellationToken)
{
return ValueTask.CompletedTask;
}
}
Loading
Loading