From 1973fb2a60156a0d95c6f53f90d472e9dd528172 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Thu, 16 Apr 2026 07:32:17 +0800
Subject: [PATCH] =?UTF-8?q?feat(ioc):=20=E6=B7=BB=E5=8A=A0Microsoft=20DI?=
=?UTF-8?q?=E5=AE=B9=E5=99=A8=E9=80=82=E9=85=8D=E5=99=A8=E5=92=8CCQRS?=
=?UTF-8?q?=E8=BF=90=E8=A1=8C=E6=97=B6=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 移除过时的Cqrs抽象引用
- 添加MicrosoftDiContainer实现IIocContainer接口
- 提供线程安全的依赖注入容器功能
- 支持单例、瞬态、作用域生命周期管理
- 实现CQRS请求管道行为注册功能
- 添加CqrsRuntimeModule服务模块
- 提供CQRS运行时实现和处理器注册器
- 扩展IArchitectureContext接口支持CQRS契约
---
.../Architectures/IArchitectureContext.cs | 2 +-
.../Cqrs/ICqrsRuntime.cs | 54 ++++---------------
.../Architectures/ArchitectureContextTests.cs | 1 -
.../Ioc/MicrosoftDiContainerTests.cs | 6 ++-
.../Architectures/ArchitectureContext.cs | 10 ++--
GFramework.Core/Ioc/MicrosoftDiContainer.cs | 11 ++--
.../Services/Modules/CqrsRuntimeModule.cs | 6 ++-
.../Cqrs/ICqrsContext.cs | 13 +++++
.../Cqrs/ICqrsRuntime.cs | 49 +++++++++++++++++
GFramework.Cqrs/CqrsRuntimeFactory.cs | 1 -
GFramework.Cqrs/Internal/CqrsDispatcher.cs | 30 ++++++-----
GFramework.Tests.Common/CqrsTestRuntime.cs | 9 +++-
12 files changed, 118 insertions(+), 74 deletions(-)
create mode 100644 GFramework.Cqrs.Abstractions/Cqrs/ICqrsContext.cs
create mode 100644 GFramework.Cqrs.Abstractions/Cqrs/ICqrsRuntime.cs
diff --git a/GFramework.Core.Abstractions/Architectures/IArchitectureContext.cs b/GFramework.Core.Abstractions/Architectures/IArchitectureContext.cs
index c7b62e2f..2e8894bc 100644
--- a/GFramework.Core.Abstractions/Architectures/IArchitectureContext.cs
+++ b/GFramework.Core.Abstractions/Architectures/IArchitectureContext.cs
@@ -18,7 +18,7 @@ namespace GFramework.Core.Abstractions.Architectures;
/// 新的 GFramework.Cqrs.Abstractions.Cqrs 契约由内置 CQRS dispatcher 统一处理,支持 request pipeline、notification publish 与 stream request。
/// 新功能优先使用 、 与对应的 CQRS Command/Query 重载;迁移旧代码时可先保留旧入口,再逐步替换为 CQRS 请求模型。
///
-public interface IArchitectureContext
+public interface IArchitectureContext : ICqrsContext
{
///
/// 获取指定类型的服务实例
diff --git a/GFramework.Core.Abstractions/Cqrs/ICqrsRuntime.cs b/GFramework.Core.Abstractions/Cqrs/ICqrsRuntime.cs
index d9efcb07..5bcbf862 100644
--- a/GFramework.Core.Abstractions/Cqrs/ICqrsRuntime.cs
+++ b/GFramework.Core.Abstractions/Cqrs/ICqrsRuntime.cs
@@ -1,52 +1,16 @@
-using GFramework.Core.Abstractions.Architectures;
-using GFramework.Cqrs.Abstractions.Cqrs;
+using System.ComponentModel;
namespace GFramework.Core.Abstractions.Cqrs;
///
-/// 定义架构上下文使用的 CQRS runtime seam。
-/// 该抽象把请求分发、通知发布与流式处理从具体实现中解耦,
-/// 使 不再直接依赖某个固定的 runtime 类型。
+/// 提供旧 GFramework.Core.Abstractions.Cqrs 命名空间下的 CQRS runtime 兼容别名。
///
-public interface ICqrsRuntime
+///
+/// 正式 runtime seam 已迁移到 ,
+/// 但当前仍保留该接口以避免立即打断历史公开路径与既有二进制引用。
+/// 新代码应优先依赖 GFramework.Cqrs.Abstractions.Cqrs 下的正式契约。
+///
+[EditorBrowsable(EditorBrowsableState.Never)]
+public interface ICqrsRuntime : GFramework.Cqrs.Abstractions.Cqrs.ICqrsRuntime
{
- ///
- /// 发送请求并返回响应。
- ///
- /// 响应类型。
- /// 当前架构上下文,用于上下文感知处理器注入与嵌套请求访问。
- /// 要分发的请求。
- /// 取消令牌。
- /// 请求响应。
- ValueTask SendAsync(
- IArchitectureContext context,
- IRequest request,
- CancellationToken cancellationToken = default);
-
- ///
- /// 发布通知到所有已注册处理器。
- ///
- /// 通知类型。
- /// 当前架构上下文,用于上下文感知处理器注入。
- /// 要发布的通知。
- /// 取消令牌。
- /// 表示通知分发完成的值任务。
- ValueTask PublishAsync(
- IArchitectureContext context,
- TNotification notification,
- CancellationToken cancellationToken = default)
- where TNotification : INotification;
-
- ///
- /// 创建流式请求的异步响应序列。
- ///
- /// 流元素类型。
- /// 当前架构上下文,用于上下文感知处理器注入。
- /// 流式请求。
- /// 取消令牌。
- /// 按需生成的异步响应序列。
- IAsyncEnumerable CreateStream(
- IArchitectureContext context,
- IStreamRequest request,
- CancellationToken cancellationToken = default);
}
diff --git a/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
index cdcde44d..584090ab 100644
--- a/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
+++ b/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
@@ -1,7 +1,6 @@
using System.Reflection;
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Command;
-using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Enums;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Ioc;
diff --git a/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs b/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
index 4104ccb1..39445d48 100644
--- a/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
+++ b/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
@@ -1,12 +1,12 @@
using System.Reflection;
using GFramework.Core.Abstractions.Bases;
-using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Ioc;
using GFramework.Core.Logging;
using GFramework.Core.Tests.Cqrs;
using GFramework.Core.Tests.Systems;
using GFramework.Cqrs.Abstractions.Cqrs;
+using LegacyICqrsRuntime = GFramework.Core.Abstractions.Cqrs.ICqrsRuntime;
namespace GFramework.Core.Tests.Ioc;
@@ -160,12 +160,16 @@ public class MicrosoftDiContainerTests
public void RegisterHandlers_Should_Not_Duplicate_Cqrs_Infrastructure_When_It_Is_Already_Registered()
{
Assert.That(_container.GetAll(), Has.Count.EqualTo(1));
+ Assert.That(_container.GetAll(), Has.Count.EqualTo(1));
Assert.That(_container.GetAll(), Has.Count.EqualTo(1));
+ Assert.That(_container.Get(), Is.SameAs(_container.Get()));
CqrsTestRuntime.RegisterHandlers(_container);
Assert.That(_container.GetAll(), Has.Count.EqualTo(1));
+ Assert.That(_container.GetAll(), Has.Count.EqualTo(1));
Assert.That(_container.GetAll(), Has.Count.EqualTo(1));
+ Assert.That(_container.Get(), Is.SameAs(_container.Get()));
}
///
diff --git a/GFramework.Core/Architectures/ArchitectureContext.cs b/GFramework.Core/Architectures/ArchitectureContext.cs
index 9b6d7dc2..e0ac2dd6 100644
--- a/GFramework.Core/Architectures/ArchitectureContext.cs
+++ b/GFramework.Core/Architectures/ArchitectureContext.cs
@@ -1,7 +1,6 @@
using System.Collections.Concurrent;
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;
@@ -190,7 +189,7 @@ public class ArchitectureContext : IArchitectureContext
/// 查询响应类型
/// 要发送的查询对象
/// 查询结果
- public TResponse SendQuery(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query)
+ public TResponse SendQuery(Cqrs.Abstractions.Cqrs.Query.IQuery query)
{
return SendQueryAsync(query).AsTask().GetAwaiter().GetResult();
}
@@ -216,8 +215,7 @@ public class ArchitectureContext : IArchitectureContext
/// 要发送的查询对象
/// 取消令牌,用于取消操作
/// 包含查询结果的ValueTask
- public async ValueTask SendQueryAsync(
- GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery query,
+ public async ValueTask SendQueryAsync(Cqrs.Abstractions.Cqrs.Query.IQuery query,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(query);
@@ -354,7 +352,7 @@ public class ArchitectureContext : IArchitectureContext
/// 取消令牌,用于取消操作
/// 包含命令执行结果的ValueTask
public async ValueTask SendCommandAsync(
- GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command,
+ Cqrs.Abstractions.Cqrs.Command.ICommand command,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(command);
@@ -393,7 +391,7 @@ public class ArchitectureContext : IArchitectureContext
/// 命令响应类型
/// 要发送的命令对象
/// 命令执行结果
- public TResponse SendCommand(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand command)
+ public TResponse SendCommand(Cqrs.Abstractions.Cqrs.Command.ICommand command)
{
return SendCommandAsync(command).AsTask().GetAwaiter().GetResult();
}
diff --git a/GFramework.Core/Ioc/MicrosoftDiContainer.cs b/GFramework.Core/Ioc/MicrosoftDiContainer.cs
index dc14485e..390f4c91 100644
--- a/GFramework.Core/Ioc/MicrosoftDiContainer.cs
+++ b/GFramework.Core/Ioc/MicrosoftDiContainer.cs
@@ -4,7 +4,6 @@ using GFramework.Core.Abstractions.Bases;
using GFramework.Core.Abstractions.Ioc;
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.Systems;
-using GFramework.Core.Logging;
using GFramework.Core.Rule;
using GFramework.Cqrs.Abstractions.Cqrs;
@@ -624,11 +623,14 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
.Where(s => s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType)).ToList();
var result = new List();
+ var seenInstances = new HashSet
/// 通知类型。
- /// 当前架构上下文,用于上下文感知处理器注入。
+ /// 当前 CQRS 分发上下文,用于上下文感知处理器注入。
/// 通知对象。
/// 取消令牌。
public async ValueTask PublishAsync(
- IArchitectureContext context,
+ ICqrsContext context,
TNotification notification,
CancellationToken cancellationToken = default)
where TNotification : INotification
@@ -75,12 +75,12 @@ internal sealed class CqrsDispatcher(
/// 发送请求并返回结果。
///
/// 响应类型。
- /// 当前架构上下文,用于上下文感知处理器注入。
+ /// 当前 CQRS 分发上下文,用于上下文感知处理器注入。
/// 请求对象。
/// 取消令牌。
/// 请求响应。
public async ValueTask SendAsync(
- IArchitectureContext context,
+ ICqrsContext context,
IRequest request,
CancellationToken cancellationToken = default)
{
@@ -122,12 +122,12 @@ internal sealed class CqrsDispatcher(
/// 创建流式请求并返回异步响应序列。
///
/// 响应元素类型。
- /// 当前架构上下文,用于上下文感知处理器注入。
+ /// 当前 CQRS 分发上下文,用于上下文感知处理器注入。
/// 流式请求对象。
/// 取消令牌。
/// 异步响应序列。
public IAsyncEnumerable CreateStream(
- IArchitectureContext context,
+ ICqrsContext context,
IStreamRequest request,
CancellationToken cancellationToken = default)
{
@@ -150,14 +150,20 @@ internal sealed class CqrsDispatcher(
}
///
- /// 为上下文感知处理器注入当前架构上下文。
+ /// 为上下文感知处理器注入当前 CQRS 分发上下文。
///
/// 处理器实例。
- /// 当前架构上下文。
- private static void PrepareHandler(object handler, IArchitectureContext context)
+ /// 当前 CQRS 分发上下文。
+ private static void PrepareHandler(object handler, ICqrsContext context)
{
if (handler is IContextAware contextAware)
- contextAware.SetContext(context);
+ {
+ if (context is not IArchitectureContext architectureContext)
+ throw new InvalidOperationException(
+ "The current CQRS context does not implement IArchitectureContext, so it cannot be injected into IContextAware handlers.");
+
+ contextAware.SetContext(architectureContext);
+ }
}
///
diff --git a/GFramework.Tests.Common/CqrsTestRuntime.cs b/GFramework.Tests.Common/CqrsTestRuntime.cs
index e7c971db..7acbbe35 100644
--- a/GFramework.Tests.Common/CqrsTestRuntime.cs
+++ b/GFramework.Tests.Common/CqrsTestRuntime.cs
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using System.Reflection;
-using GFramework.Core.Abstractions.Cqrs;
using GFramework.Core.Abstractions.Ioc;
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Ioc;
using GFramework.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs;
using GFramework.Cqrs.Command;
+using LegacyICqrsRuntime = GFramework.Core.Abstractions.Cqrs.ICqrsRuntime;
namespace GFramework.Tests.Common;
@@ -60,7 +60,12 @@ public static class CqrsTestRuntime
{
var runtimeLogger = LoggerFactoryResolver.Provider.CreateLogger("CqrsDispatcher");
var runtime = CqrsRuntimeFactory.CreateRuntime(container, runtimeLogger);
- container.Register(runtime);
+ container.Register(runtime);
+ container.Register((LegacyICqrsRuntime)runtime);
+ }
+ else if (container.Get() is null)
+ {
+ container.Register((LegacyICqrsRuntime)container.GetRequired());
}
if (container.Get() is null)