From 0d9d09bc4ab4f06d54edad54a8a86b330c46a3f6 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Thu, 16 Apr 2026 09:14:27 +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=8F=8A=E6=B5=8B?=
=?UTF-8?q?=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 实现MicrosoftDiContainer类作为IIocContainer接口的适配器
- 提供线程安全的依赖注入容器功能
- 支持单例、瞬态、作用域服务注册
- 实现CQRS处理器注册功能
- 添加服务工厂方法注册支持
- 实现按优先级排序的服务获取功能
- 添加完整的单元测试覆盖基本功能和边界情况
- 支持容器冻结和作用域创建功能
- 实现多样性实例注册到多个接口的功能
---
.../Ioc/MicrosoftDiContainerTests.cs | 62 +++++++
GFramework.Core/Ioc/MicrosoftDiContainer.cs | 168 ++++++++++++------
.../Cqrs/ICqrsRuntime.cs | 32 ++++
.../Internal/CqrsHandlerRegistrar.cs | 2 +
.../DefaultCqrsRegistrationService.cs | 5 +-
5 files changed, 215 insertions(+), 54 deletions(-)
diff --git a/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs b/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
index 39445d48..4e3b5b23 100644
--- a/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
+++ b/GFramework.Core.Tests/Ioc/MicrosoftDiContainerTests.cs
@@ -249,6 +249,46 @@ public class MicrosoftDiContainerTests
Assert.That(results.Count, Is.EqualTo(0));
}
+ ///
+ /// 测试容器未冻结时,会折叠“不同服务类型指向同一实例”的兼容别名重复,
+ /// 但会保留同一服务类型的重复显式注册。
+ ///
+ [Test]
+ public void GetAll_Should_Preserve_Duplicate_Registrations_For_The_Same_ServiceType_While_Deduplicating_Aliases()
+ {
+ var instance = new AliasAwareService();
+
+ _container.Register(instance);
+ _container.Register(instance);
+ _container.Register(instance);
+
+ var results = _container.GetAll();
+
+ Assert.That(results, Has.Count.EqualTo(2));
+ Assert.That(results[0], Is.SameAs(instance));
+ Assert.That(results[1], Is.SameAs(instance));
+ }
+
+ ///
+ /// 测试非泛型 GetAll 在容器未冻结时与泛型重载保持相同的别名去重语义。
+ ///
+ [Test]
+ public void
+ GetAll_Type_Should_Preserve_Duplicate_Registrations_For_The_Same_ServiceType_While_Deduplicating_Aliases()
+ {
+ var instance = new AliasAwareService();
+
+ _container.Register(instance);
+ _container.Register(instance);
+ _container.Register(instance);
+
+ var results = _container.GetAll(typeof(ISharedAliasService));
+
+ Assert.That(results, Has.Count.EqualTo(2));
+ Assert.That(results[0], Is.SameAs(instance));
+ Assert.That(results[1], Is.SameAs(instance));
+ }
+
///
/// 测试获取排序后的所有实例的功能
///
@@ -716,6 +756,28 @@ public interface IMixedService
string? Name { get; set; }
}
+///
+/// 用于验证未冻结查询路径中的服务别名去重行为。
+///
+public interface ISharedAliasService;
+
+///
+/// 主服务别名接口。
+///
+public interface IPrimaryAliasService : ISharedAliasService;
+
+///
+/// 次级兼容别名接口。
+///
+public interface ISecondaryAliasService : ISharedAliasService;
+
+///
+/// 同时实现多个别名接口的测试服务。
+///
+public sealed class AliasAwareService : IPrimaryAliasService, ISecondaryAliasService
+{
+}
+
///
/// 实现优先级的服务
///
diff --git a/GFramework.Core/Ioc/MicrosoftDiContainer.cs b/GFramework.Core/Ioc/MicrosoftDiContainer.cs
index 78295ed4..5c49621a 100644
--- a/GFramework.Core/Ioc/MicrosoftDiContainer.cs
+++ b/GFramework.Core/Ioc/MicrosoftDiContainer.cs
@@ -35,6 +35,14 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
#endregion
+ ///
+ /// 记录某个实例在未冻结查询中可见的服务类型分组信息。
+ ///
+ /// 当前分组对应的服务类型。
+ /// 该服务类型下的描述符数量。
+ /// 该服务类型首次出现的位置,用于稳定打破并列。
+ private sealed record VisibleServiceTypeGroup(Type ServiceType, int Count, int FirstIndex);
+
#region Fields
///
@@ -593,32 +601,7 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
{
if (_provider == null)
{
- // 如果容器未冻结,从服务集合中获取已注册的实例
- var serviceType = typeof(T);
- var registeredServices = GetServicesUnsafe
- .Where(s => s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType)).ToList();
-
- var result = new List();
- var seenInstances = new HashSet
/// 服务类型
/// 只读的服务实例列表
- /// 当容器未冻结时抛出
+ /// 当 为 时抛出
public IReadOnlyList