feat(architecture): 添加按优先级获取服务实例的功能

- 在 ArchitectureContext 中添加 GetServicesByPriority、GetSystemsByPriority、
  GetModelsByPriority 和 GetUtilitiesByPriority 方法
- 在 ContextAwareServiceExtensions 中添加对应的扩展方法支持按优先级获取实例
- 在 MicrosoftDiContainer 中实现 GetAllByPriority 方法和 SortByPriority 排序逻辑
- 在抽象层定义 IPrioritized 接口用于标记可排序的服务组件
- 为 PauseToken 添加完整的相等性比较和字符串转换方法
- 添加全面的单元测试验证优先级排序功能的正确性
This commit is contained in:
GeWuYou 2026-03-05 21:29:45 +08:00 committed by gewuyou
parent b4d17edeee
commit f8c39e46a5
11 changed files with 771 additions and 1 deletions

View File

@ -71,6 +71,38 @@ public interface IArchitectureContext
/// <returns>所有符合条件的工具类实例列表</returns>
IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, IUtility;
/// <summary>
/// 获取指定类型的所有服务实例,并按优先级排序
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TService">服务类型</typeparam>
/// <returns>按优先级排序后的服务实例列表</returns>
IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class;
/// <summary>
/// 获取指定类型的所有系统实例,并按优先级排序
/// 实现 IPrioritized 接口的系统将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TSystem">系统类型必须继承自ISystem接口</typeparam>
/// <returns>按优先级排序后的系统实例列表</returns>
IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem;
/// <summary>
/// 获取指定类型的所有模型实例,并按优先级排序
/// 实现 IPrioritized 接口的模型将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TModel">模型类型必须继承自IModel接口</typeparam>
/// <returns>按优先级排序后的模型实例列表</returns>
IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel;
/// <summary>
/// 获取指定类型的所有工具类实例,并按优先级排序
/// 实现 IPrioritized 接口的工具将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TUtility">工具类类型必须继承自IUtility接口</typeparam>
/// <returns>按优先级排序后的工具类实例列表</returns>
IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility;
/// <summary>
/// 发送一个命令
/// </summary>

View File

@ -0,0 +1,17 @@
namespace GFramework.Core.Abstractions.bases;
/// <summary>
/// 定义具有优先级的对象接口。
/// 数值越小优先级越高,越先执行。
/// 用于控制服务、系统等组件的执行顺序。
/// </summary>
public interface IPrioritized
{
/// <summary>
/// 获取优先级值。
/// 数值越小优先级越高。
/// 默认优先级为 0。
/// 建议范围:-1000 到 1000。
/// </summary>
int Priority { get; }
}

View File

@ -165,6 +165,24 @@ public interface IIocContainer : IContextAware
/// <returns>按指定方式排序后的实例列表</returns>
IReadOnlyList<T> GetAllSorted<T>(Comparison<T> comparison) where T : class;
/// <summary>
/// 获取指定类型的所有实例,并按优先级排序
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
/// 未实现 IPrioritized 的服务将使用默认优先级 0
/// </summary>
/// <typeparam name="T">期望获取的实例类型</typeparam>
/// <returns>按优先级排序后的实例列表</returns>
IReadOnlyList<T> GetAllByPriority<T>() where T : class;
/// <summary>
/// 获取指定类型的所有实例,并按优先级排序
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
/// 未实现 IPrioritized 的服务将使用默认优先级 0
/// </summary>
/// <param name="type">期望获取的实例类型</param>
/// <returns>按优先级排序后的实例列表</returns>
IReadOnlyList<object> GetAllByPriority(Type type);
#endregion
#region Utility Methods

View File

@ -18,7 +18,7 @@ public readonly struct PauseToken : IEquatable<PauseToken>
/// <summary>
/// 创建暂停令牌
/// </summary>
/// <param name="id">令牌 ID</param>
/// <param name="id">令牌 ID,用于唯一标识暂停请求</param>
public PauseToken(Guid id)
{
Id = id;
@ -27,17 +27,48 @@ public readonly struct PauseToken : IEquatable<PauseToken>
/// <summary>
/// 创建无效令牌
/// </summary>
/// <returns>返回一个 ID 为 Guid.Empty 的无效暂停令牌</returns>
public static PauseToken Invalid => new(Guid.Empty);
/// <summary>
/// 判断当前令牌是否与另一个令牌相等
/// </summary>
/// <param name="other">要比较的另一个暂停令牌</param>
/// <returns>如果两个令牌的 ID 相同则返回 true否则返回 false</returns>
public bool Equals(PauseToken other) => Id.Equals(other.Id);
/// <summary>
/// 判断当前对象是否为暂停令牌类型并与其相等
/// </summary>
/// <param name="obj">要比较的对象</param>
/// <returns>如果对象是 PauseToken 类型且 ID 相同则返回 true否则返回 false</returns>
public override bool Equals(object? obj) => obj is PauseToken other && Equals(other);
/// <summary>
/// 获取令牌的哈希码
/// </summary>
/// <returns>基于令牌 ID 计算的哈希值</returns>
public override int GetHashCode() => Id.GetHashCode();
/// <summary>
/// 重载等于运算符,判断两个暂停令牌是否相等
/// </summary>
/// <param name="left">左侧暂停令牌</param>
/// <param name="right">右侧暂停令牌</param>
/// <returns>如果两个令牌相等则返回 true否则返回 false</returns>
public static bool operator ==(PauseToken left, PauseToken right) => left.Equals(right);
/// <summary>
/// 重载不等于运算符,判断两个暂停令牌是否不相等
/// </summary>
/// <param name="left">左侧暂停令牌</param>
/// <param name="right">右侧暂停令牌</param>
/// <returns>如果两个令牌不相等则返回 true否则返回 false</returns>
public static bool operator !=(PauseToken left, PauseToken right) => !left.Equals(right);
/// <summary>
/// 将暂停令牌转换为字符串表示形式
/// </summary>
/// <returns>包含令牌 ID 信息的字符串</returns>
public override string ToString() => $"PauseToken({Id})";
}

View File

@ -340,6 +340,26 @@ public class TestArchitectureContextV3 : IArchitectureContext
return _container.GetAll<TUtility>();
}
public IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class
{
return _container.GetAllByPriority<TService>();
}
public IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem
{
return _container.GetAllByPriority<TSystem>();
}
public IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel
{
return _container.GetAllByPriority<TModel>();
}
public IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility
{
return _container.GetAllByPriority<TUtility>();
}
public void SendEvent<TEvent>() where TEvent : new()
{
}

View File

@ -338,6 +338,26 @@ public class TestArchitectureContext : IArchitectureContext
return _container.GetAll<TUtility>();
}
public IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class
{
return _container.GetAllByPriority<TService>();
}
public IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem
{
return _container.GetAllByPriority<TSystem>();
}
public IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel
{
return _container.GetAllByPriority<TModel>();
}
public IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility
{
return _container.GetAllByPriority<TUtility>();
}
/// <summary>
/// 发送事件
/// </summary>

View File

@ -0,0 +1,249 @@
using System.Reflection;
using GFramework.Core.Abstractions.bases;
using GFramework.Core.Abstractions.model;
using GFramework.Core.Abstractions.system;
using GFramework.Core.Abstractions.utility;
using GFramework.Core.ioc;
using GFramework.Core.logging;
using GFramework.Core.model;
using GFramework.Core.system;
using NUnit.Framework;
namespace GFramework.Core.Tests.architecture;
/// <summary>
/// 优先级服务排序的集成测试
/// 测试完整的架构集成场景
/// </summary>
[TestFixture]
public class PriorityServiceTests
{
[SetUp]
public void SetUp()
{
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
_container = new MicrosoftDiContainer();
// 初始化 logger 字段
var loggerField = typeof(MicrosoftDiContainer).GetField("_logger",
BindingFlags.NonPublic | BindingFlags.Instance);
loggerField?.SetValue(_container,
LoggerFactoryResolver.Provider.CreateLogger(nameof(MicrosoftDiContainer)));
}
private MicrosoftDiContainer _container = null!;
/// <summary>
/// 测试系统按优先级排序
/// </summary>
[Test]
public void Systems_Should_Be_Sorted_By_Priority()
{
// Arrange
_container.Register<IPriorityTestSystem>(new PriorityTestSystemC());
_container.Register<IPriorityTestSystem>(new PriorityTestSystemA());
_container.Register<IPriorityTestSystem>(new PriorityTestSystemB());
_container.Freeze();
// Act
var systems = _container.GetAllByPriority<IPriorityTestSystem>();
// Assert
Assert.That(systems, Has.Count.EqualTo(3));
Assert.That(systems[0], Is.InstanceOf<PriorityTestSystemA>()); // Priority = 10
Assert.That(systems[1], Is.InstanceOf<PriorityTestSystemB>()); // Priority = 20
Assert.That(systems[2], Is.InstanceOf<PriorityTestSystemC>()); // Priority = 30
}
/// <summary>
/// 测试模型按优先级排序
/// </summary>
[Test]
public void Models_Should_Be_Sorted_By_Priority()
{
// Arrange
_container.Register<IPriorityTestModel>(new PriorityTestModelC());
_container.Register<IPriorityTestModel>(new PriorityTestModelA());
_container.Register<IPriorityTestModel>(new PriorityTestModelB());
_container.Freeze();
// Act
var models = _container.GetAllByPriority<IPriorityTestModel>();
// Assert
Assert.That(models, Has.Count.EqualTo(3));
Assert.That(models[0], Is.InstanceOf<PriorityTestModelA>()); // Priority = 10
Assert.That(models[1], Is.InstanceOf<PriorityTestModelB>()); // Priority = 20
Assert.That(models[2], Is.InstanceOf<PriorityTestModelC>()); // Priority = 30
}
/// <summary>
/// 测试工具按优先级排序
/// </summary>
[Test]
public void Utilities_Should_Be_Sorted_By_Priority()
{
// Arrange
_container.Register<IPriorityTestUtility>(new PriorityTestUtilityC());
_container.Register<IPriorityTestUtility>(new PriorityTestUtilityA());
_container.Register<IPriorityTestUtility>(new PriorityTestUtilityB());
_container.Freeze();
// Act
var utilities = _container.GetAllByPriority<IPriorityTestUtility>();
// Assert
Assert.That(utilities, Has.Count.EqualTo(3));
Assert.That(utilities[0], Is.InstanceOf<PriorityTestUtilityA>()); // Priority = 10
Assert.That(utilities[1], Is.InstanceOf<PriorityTestUtilityB>()); // Priority = 20
Assert.That(utilities[2], Is.InstanceOf<PriorityTestUtilityC>()); // Priority = 30
}
/// <summary>
/// 测试混合优先级和非优先级服务
/// </summary>
[Test]
public void Mixed_Prioritized_And_Non_Prioritized_Should_Work()
{
// Arrange
_container.Register<IMixedTestSystem>(new MixedTestSystemWithPriority());
_container.Register<IMixedTestSystem>(new MixedTestSystemWithoutPriority());
_container.Register<IMixedTestSystem>(new MixedTestSystemNegativePriority());
_container.Freeze();
// Act
var systems = _container.GetAllByPriority<IMixedTestSystem>();
// Assert
Assert.That(systems, Has.Count.EqualTo(3));
Assert.That(systems[0], Is.InstanceOf<MixedTestSystemNegativePriority>()); // -10
Assert.That(systems[1], Is.InstanceOf<MixedTestSystemWithoutPriority>()); // 0 (默认)
Assert.That(systems[2], Is.InstanceOf<MixedTestSystemWithPriority>()); // 10
}
}
#region Test Interfaces
public interface IPriorityTestSystem : ISystem
{
}
public interface IPriorityTestModel : IModel
{
}
public interface IPriorityTestUtility : IUtility
{
}
public interface IMixedTestSystem : ISystem
{
}
#endregion
#region Test Systems
public class PriorityTestSystemA : AbstractSystem, IPriorityTestSystem, IPrioritized
{
public int Priority => 10;
protected override void OnInit()
{
}
}
public class PriorityTestSystemB : AbstractSystem, IPriorityTestSystem, IPrioritized
{
public int Priority => 20;
protected override void OnInit()
{
}
}
public class PriorityTestSystemC : AbstractSystem, IPriorityTestSystem, IPrioritized
{
public int Priority => 30;
protected override void OnInit()
{
}
}
public class MixedTestSystemWithPriority : AbstractSystem, IMixedTestSystem, IPrioritized
{
public int Priority => 10;
protected override void OnInit()
{
}
}
public class MixedTestSystemWithoutPriority : AbstractSystem, IMixedTestSystem
{
protected override void OnInit()
{
}
}
public class MixedTestSystemNegativePriority : AbstractSystem, IMixedTestSystem, IPrioritized
{
public int Priority => -10;
protected override void OnInit()
{
}
}
#endregion
#region Test Models
public class PriorityTestModelA : AbstractModel, IPriorityTestModel, IPrioritized
{
public int Priority => 10;
protected override void OnInit()
{
}
}
public class PriorityTestModelB : AbstractModel, IPriorityTestModel, IPrioritized
{
public int Priority => 20;
protected override void OnInit()
{
}
}
public class PriorityTestModelC : AbstractModel, IPriorityTestModel, IPrioritized
{
public int Priority => 30;
protected override void OnInit()
{
}
}
#endregion
#region Test Utilities
public class PriorityTestUtilityA : IPriorityTestUtility, IPrioritized
{
public int Priority => 10;
}
public class PriorityTestUtilityB : IPriorityTestUtility, IPrioritized
{
public int Priority => 20;
}
public class PriorityTestUtilityC : IPriorityTestUtility, IPrioritized
{
public int Priority => 30;
}
#endregion

View File

@ -1,4 +1,5 @@
using System.Reflection;
using GFramework.Core.Abstractions.bases;
using GFramework.Core.ioc;
using GFramework.Core.logging;
using GFramework.Core.Tests.system;
@ -433,6 +434,200 @@ public class MicrosoftDiContainerTests
// Assert
Assert.DoesNotThrow(() => Task.WaitAll(tasks));
}
/// <summary>
/// 测试按优先级排序功能 - 升序排序
/// </summary>
[Test]
public void GetAllByPriority_Should_Sort_By_Priority_Ascending()
{
// Arrange
var service1 = new PrioritizedService { Priority = 30 };
var service2 = new PrioritizedService { Priority = 10 };
var service3 = new PrioritizedService { Priority = 20 };
_container.Register<IPrioritizedService>(service1);
_container.Register<IPrioritizedService>(service2);
_container.Register<IPrioritizedService>(service3);
_container.Freeze();
// Act
var services = _container.GetAllByPriority<IPrioritizedService>();
// Assert
Assert.That(services, Has.Count.EqualTo(3));
Assert.That(services[0].Priority, Is.EqualTo(10)); // 最小优先级在前
Assert.That(services[1].Priority, Is.EqualTo(20));
Assert.That(services[2].Priority, Is.EqualTo(30));
}
/// <summary>
/// 测试未实现 IPrioritized 的服务使用默认优先级 0
/// </summary>
[Test]
public void GetAllByPriority_Should_Use_Default_Priority_For_Non_Prioritized()
{
// Arrange
var service1 = new PrioritizedService { Priority = 10 };
var service2 = new NonPrioritizedService();
var service3 = new PrioritizedService { Priority = -10 };
_container.Register<IMixedService>(service1);
_container.Register<IMixedService>(service2);
_container.Register<IMixedService>(service3);
_container.Freeze();
// Act
var services = _container.GetAllByPriority<IMixedService>();
// Assert
Assert.That(services, Has.Count.EqualTo(3));
Assert.That(services[0], Is.SameAs(service3)); // -10
Assert.That(services[1], Is.SameAs(service2)); // 0 (默认)
Assert.That(services[2], Is.SameAs(service1)); // 10
}
/// <summary>
/// 测试相同优先级保持注册顺序(稳定排序)
/// </summary>
[Test]
public void GetAllByPriority_Should_Preserve_Registration_Order_For_Equal_Priorities()
{
// Arrange
var service1 = new PrioritizedService { Priority = 10, Name = "First" };
var service2 = new PrioritizedService { Priority = 10, Name = "Second" };
var service3 = new PrioritizedService { Priority = 10, Name = "Third" };
_container.Register<IPrioritizedService>(service1);
_container.Register<IPrioritizedService>(service2);
_container.Register<IPrioritizedService>(service3);
_container.Freeze();
// Act
var services = _container.GetAllByPriority<IPrioritizedService>();
// Assert
Assert.That(services, Has.Count.EqualTo(3));
Assert.That(services[0].Name, Is.EqualTo("First"));
Assert.That(services[1].Name, Is.EqualTo("Second"));
Assert.That(services[2].Name, Is.EqualTo("Third"));
}
/// <summary>
/// 测试空列表处理
/// </summary>
[Test]
public void GetAllByPriority_Should_Handle_Empty_List()
{
// Arrange
_container.Freeze();
// Act
var services = _container.GetAllByPriority<IPrioritizedService>();
// Assert
Assert.That(services, Is.Empty);
}
/// <summary>
/// 测试单项列表处理
/// </summary>
[Test]
public void GetAllByPriority_Should_Handle_Single_Item()
{
// Arrange
var service = new PrioritizedService { Priority = 42 };
_container.RegisterSingleton<IPrioritizedService>(service);
_container.Freeze();
// Act
var services = _container.GetAllByPriority<IPrioritizedService>();
// Assert
Assert.That(services, Has.Count.EqualTo(1));
Assert.That(services[0], Is.SameAs(service));
}
/// <summary>
/// 测试负数优先级处理
/// </summary>
[Test]
public void GetAllByPriority_Should_Handle_Negative_Priorities()
{
// Arrange
var service1 = new PrioritizedService { Priority = -100 };
var service2 = new PrioritizedService { Priority = 0 };
var service3 = new PrioritizedService { Priority = 100 };
var service4 = new PrioritizedService { Priority = -50 };
_container.Register<IPrioritizedService>(service1);
_container.Register<IPrioritizedService>(service2);
_container.Register<IPrioritizedService>(service3);
_container.Register<IPrioritizedService>(service4);
_container.Freeze();
// Act
var services = _container.GetAllByPriority<IPrioritizedService>();
// Assert
Assert.That(services, Has.Count.EqualTo(4));
Assert.That(services[0].Priority, Is.EqualTo(-100));
Assert.That(services[1].Priority, Is.EqualTo(-50));
Assert.That(services[2].Priority, Is.EqualTo(0));
Assert.That(services[3].Priority, Is.EqualTo(100));
}
/// <summary>
/// 测试混合优先级和非优先级服务
/// </summary>
[Test]
public void GetAllByPriority_Should_Handle_Mixed_Prioritized_And_Non_Prioritized()
{
// Arrange
var service1 = new PrioritizedService { Priority = 50, Name = "P50" };
var service2 = new NonPrioritizedService { Name = "NP1" };
var service3 = new PrioritizedService { Priority = -50, Name = "P-50" };
var service4 = new NonPrioritizedService { Name = "NP2" };
_container.Register<IMixedService>(service1);
_container.Register<IMixedService>(service2);
_container.Register<IMixedService>(service3);
_container.Register<IMixedService>(service4);
_container.Freeze();
// Act
var services = _container.GetAllByPriority<IMixedService>();
// Assert
Assert.That(services, Has.Count.EqualTo(4));
Assert.That(services[0].Name, Is.EqualTo("P-50")); // -50
Assert.That(services[1].Name, Is.EqualTo("NP1")); // 0 (默认)
Assert.That(services[2].Name, Is.EqualTo("NP2")); // 0 (默认)
Assert.That(services[3].Name, Is.EqualTo("P50")); // 50
}
/// <summary>
/// 测试 GetAllByPriority(Type) 重载方法
/// </summary>
[Test]
public void GetAllByPriority_Type_Should_Sort_Correctly()
{
// Arrange
var service1 = new PrioritizedService { Priority = 30 };
var service2 = new PrioritizedService { Priority = 10 };
_container.Register<IPrioritizedService>(service1);
_container.Register<IPrioritizedService>(service2);
_container.Freeze();
// Act
var services = _container.GetAllByPriority(typeof(IPrioritizedService));
// Assert
Assert.That(services, Has.Count.EqualTo(2));
Assert.That(((IPrioritizedService)services[0]).Priority, Is.EqualTo(10));
Assert.That(((IPrioritizedService)services[1]).Priority, Is.EqualTo(30));
}
}
/// <summary>
@ -449,4 +644,37 @@ public sealed class TestService : IService
/// 获取或设置优先级
/// </summary>
public int Priority { get; set; }
}
/// <summary>
/// 优先级服务接口
/// </summary>
public interface IPrioritizedService : IPrioritized
{
string? Name { get; set; }
}
/// <summary>
/// 混合服务接口(用于测试优先级和非优先级混合)
/// </summary>
public interface IMixedService
{
string? Name { get; set; }
}
/// <summary>
/// 实现优先级的服务
/// </summary>
public sealed class PrioritizedService : IPrioritizedService, IMixedService
{
public int Priority { get; set; }
public string? Name { get; set; }
}
/// <summary>
/// 不实现优先级的服务
/// </summary>
public sealed class NonPrioritizedService : IMixedService
{
public string? Name { get; set; }
}

View File

@ -303,6 +303,50 @@ public class ArchitectureContext(IIocContainer container) : IArchitectureContext
return _container.GetAll<TUtility>();
}
/// <summary>
/// 获取指定类型的所有服务实例,并按优先级排序
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TService">服务类型</typeparam>
/// <returns>按优先级排序后的服务实例列表</returns>
public IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class
{
return _container.GetAllByPriority<TService>();
}
/// <summary>
/// 获取指定类型的所有系统实例,并按优先级排序
/// 实现 IPrioritized 接口的系统将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TSystem">系统类型</typeparam>
/// <returns>按优先级排序后的系统实例列表</returns>
public IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem
{
return _container.GetAllByPriority<TSystem>();
}
/// <summary>
/// 获取指定类型的所有模型实例,并按优先级排序
/// 实现 IPrioritized 接口的模型将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TModel">模型类型</typeparam>
/// <returns>按优先级排序后的模型实例列表</returns>
public IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel
{
return _container.GetAllByPriority<TModel>();
}
/// <summary>
/// 获取指定类型的所有工具实例,并按优先级排序
/// 实现 IPrioritized 接口的工具将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TUtility">工具类型</typeparam>
/// <returns>按优先级排序后的工具实例列表</returns>
public IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility
{
return _container.GetAllByPriority<TUtility>();
}
#endregion
#region Command Execution

View File

@ -133,5 +133,65 @@ public static class ContextAwareServiceExtensions
return context.GetUtilities<TUtility>();
}
/// <summary>
/// 获取指定类型的所有服务实例,并按优先级排序
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TService">服务类型</typeparam>
/// <param name="contextAware">上下文感知对象</param>
/// <returns>按优先级排序后的服务实例列表</returns>
public static IReadOnlyList<TService> GetServicesByPriority<TService>(this IContextAware contextAware)
where TService : class
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
return context.GetServicesByPriority<TService>();
}
/// <summary>
/// 获取指定类型的所有系统实例,并按优先级排序
/// 实现 IPrioritized 接口的系统将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TSystem">系统类型</typeparam>
/// <param name="contextAware">上下文感知对象</param>
/// <returns>按优先级排序后的系统实例列表</returns>
public static IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>(this IContextAware contextAware)
where TSystem : class, ISystem
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
return context.GetSystemsByPriority<TSystem>();
}
/// <summary>
/// 获取指定类型的所有模型实例,并按优先级排序
/// 实现 IPrioritized 接口的模型将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TModel">模型类型</typeparam>
/// <param name="contextAware">上下文感知对象</param>
/// <returns>按优先级排序后的模型实例列表</returns>
public static IReadOnlyList<TModel> GetModelsByPriority<TModel>(this IContextAware contextAware)
where TModel : class, IModel
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
return context.GetModelsByPriority<TModel>();
}
/// <summary>
/// 获取指定类型的所有工具实例,并按优先级排序
/// 实现 IPrioritized 接口的工具将按优先级排序(数值越小优先级越高)
/// </summary>
/// <typeparam name="TUtility">工具类型</typeparam>
/// <param name="contextAware">上下文感知对象</param>
/// <returns>按优先级排序后的工具实例列表</returns>
public static IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>(this IContextAware contextAware)
where TUtility : class, IUtility
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
return context.GetUtilitiesByPriority<TUtility>();
}
#endregion
}

View File

@ -1,3 +1,4 @@
using GFramework.Core.Abstractions.bases;
using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.system;
@ -594,6 +595,56 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
return list;
}
/// <summary>
/// 获取指定类型的所有实例,并按优先级排序
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
/// 未实现 IPrioritized 的服务将使用默认优先级 0
/// </summary>
/// <typeparam name="T">期望获取的实例类型</typeparam>
/// <returns>按优先级排序后的实例列表</returns>
public IReadOnlyList<T> GetAllByPriority<T>() where T : class
{
var services = GetAll<T>();
return SortByPriority(services);
}
/// <summary>
/// 获取指定类型的所有实例,并按优先级排序
/// 实现 IPrioritized 接口的服务将按值越小优先级越高)
/// 未实现 IPrioritized 的服务将使用默认优先级 0
/// </summary>
/// <param name="type">期望获取的实例类型</param>
/// <returns>按优先级排序后的实例列表</returns>
public IReadOnlyList<object> GetAllByPriority(Type type)
{
var services = GetAll(type);
return SortByPriority(services);
}
/// <summary>
/// 按优先级排序服务列表
/// 实现 IPrioritized 接口的服务按 Priority 属性排序(升序)
/// 未实现接口的服务使用默认优先级 0
/// 相同优先级保持原有注册顺序(稳定排序)
/// </summary>
private static IReadOnlyList<T> SortByPriority<T>(IReadOnlyList<T> services) where T : class
{
if (services.Count <= 1)
return services;
var list = services.ToList();
// 稳定排序:相同优先级保持注册顺序
list.Sort((a, b) =>
{
var priorityA = a is IPrioritized pa ? pa.Priority : 0;
var priorityB = b is IPrioritized pb ? pb.Priority : 0;
return priorityA.CompareTo(priorityB); // 升序
});
return list;
}
#endregion
#region Utility