GFramework/GFramework.Core/ioc/MicrosoftDiContainer.cs
GeWuYou 16d8cad4f3 refactor(ioc): 优化依赖注入容器的优先级排序实现
- 修改 MicrosoftDiContainer 中 GetAllByPriority 方法的排序逻辑,使用 OrderBy 确保稳定排序
- 修正注释中的中文描述,明确优先级排序规则
- 将 PriorityUsageAnalyzer 中的硬编码诊断规则替换为统一的 PriorityDiagnostic
- 在 PriorityGenerator 中添加对嵌套类的支持检查,报告 GF_Priority_005 错误
- 改进生成文件的命名策略,使用完整元数据名称避免冲突
- 更新 AnalyzerReleases.Unshipped.md 文档,添加新的诊断规则说明
- 移除 PriorityGeneratorSnapshotTests 中关于嵌套类的测试用例
2026-03-05 22:52:59 +08:00

782 lines
25 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using GFramework.Core.Abstractions.bases;
using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.system;
using GFramework.Core.logging;
using GFramework.Core.rule;
using Mediator;
using Microsoft.Extensions.DependencyInjection;
namespace GFramework.Core.ioc;
/// <summary>
/// Microsoft.Extensions.DependencyInjection 适配器
/// 将 Microsoft DI 包装为 IIocContainer 接口实现
/// 提供线程安全的依赖注入容器功能
/// </summary>
/// <param name="serviceCollection">可选的IServiceCollection实例默认创建新的ServiceCollection</param>
public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) : ContextAwareBase, IIocContainer
{
#region Helper Methods
/// <summary>
/// 检查容器是否已冻结,如果已冻结则抛出异常
/// 用于保护注册操作的安全性
/// </summary>
/// <exception cref="InvalidOperationException">当容器已冻结时抛出</exception>
private void ThrowIfFrozen()
{
if (!_frozen) return;
const string errorMsg = "MicrosoftDiContainer is frozen";
_logger.Error(errorMsg);
throw new InvalidOperationException(errorMsg);
}
#endregion
#region Fields
/// <summary>
/// 服务提供者,在容器冻结后构建,用于解析服务实例
/// </summary>
private IServiceProvider? _provider;
/// <summary>
/// 容器冻结状态标志true表示容器已冻结不可修改
/// </summary>
private volatile bool _frozen;
/// <summary>
/// 读写锁,确保多线程环境下的线程安全操作
/// </summary>
private readonly ReaderWriterLockSlim _lock = new(LockRecursionPolicy.NoRecursion);
/// <summary>
/// 已注册实例的集合,用于快速检查实例是否存在
/// </summary>
private readonly HashSet<object> _registeredInstances = [];
/// <summary>
/// 日志记录器,用于记录容器操作日志
/// </summary>
private readonly ILogger _logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(MicrosoftDiContainer));
#endregion
#region Register
/// <summary>
/// 注册单例服务实例
/// 确保同一类型只能注册一次,避免重复注册
/// </summary>
/// <typeparam name="T">服务类型</typeparam>
/// <param name="instance">要注册的实例对象</param>
/// <exception cref="InvalidOperationException">当容器已冻结或类型已被注册时抛出</exception>
public void RegisterSingleton<T>(T instance)
{
var type = typeof(T);
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
// 检查是否已注册该类型,防止重复注册
if (GetServicesUnsafe.Any(s => s.ServiceType == type))
{
var errorMsg = $"Singleton already registered for type: {type.Name}";
_logger.Error(errorMsg);
throw new InvalidOperationException(errorMsg);
}
GetServicesUnsafe.AddSingleton(type, instance!);
_registeredInstances.Add(instance!);
_logger.Debug($"Singleton registered: {type.Name}");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册单例服务,指定服务类型和实现类型
/// 直接使用底层DI容器注册类型映射关系
/// </summary>
/// <typeparam name="TService">服务接口或基类类型</typeparam>
/// <typeparam name="TImpl">具体的实现类型</typeparam>
public void RegisterSingleton<TService, TImpl>()
where TImpl : class, TService
where TService : class
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
GetServicesUnsafe.AddSingleton<TService, TImpl>();
_logger.Debug($"Singleton registered: {typeof(TService).Name}");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册瞬态服务,指定服务类型和实现类型
/// 每次解析时都会创建新的实例
/// </summary>
/// <typeparam name="TService">服务接口或基类类型</typeparam>
/// <typeparam name="TImpl">具体的实现类型</typeparam>
public void RegisterTransient<TService, TImpl>()
where TImpl : class, TService
where TService : class
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
GetServicesUnsafe.AddTransient<TService, TImpl>();
_logger.Debug($"Transient registered: {typeof(TService).Name}");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册作用域服务,指定服务类型和实现类型
/// 在同一作用域内共享实例,不同作用域使用不同实例
/// </summary>
/// <typeparam name="TService">服务接口或基类类型</typeparam>
/// <typeparam name="TImpl">具体的实现类型</typeparam>
public void RegisterScoped<TService, TImpl>()
where TImpl : class, TService
where TService : class
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
GetServicesUnsafe.AddScoped<TService, TImpl>();
_logger.Debug($"Scoped registered: {typeof(TService).Name}");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册多个实例到其所有接口和具体类型
/// 实现一个实例支持多种接口类型的解析
/// </summary>
/// <param name="instance">要注册的对象实例</param>
/// <exception cref="InvalidOperationException">当容器已冻结时抛出</exception>
public void RegisterPlurality(object instance)
{
var concreteType = instance.GetType();
var interfaces = concreteType.GetInterfaces();
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
// 注册具体类型映射
GetServicesUnsafe.AddSingleton(concreteType, instance);
// 注册所有接口类型映射(指向同一实例)
foreach (var interfaceType in interfaces)
{
GetServicesUnsafe.AddSingleton(interfaceType, _ => instance);
}
_registeredInstances.Add(instance);
_logger.Debug($"Plurality registered: {concreteType.Name} with {interfaces.Length} interfaces");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册多个实例到其所有接口
/// 实现一个实例支持多种接口类型的解析
/// </summary>
public void RegisterPlurality<T>() where T : class
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
var concreteType = typeof(T);
var interfaces = concreteType.GetInterfaces();
// 注册具体类型
GetServicesUnsafe.AddSingleton<T>();
// 注册所有接口(指向同一个实例)
foreach (var interfaceType in interfaces)
{
GetServicesUnsafe.AddSingleton(interfaceType, sp => sp.GetRequiredService<T>());
}
_logger.Debug($"Type registered: {concreteType.Name} with {interfaces.Length} interfaces");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册系统实例
/// 通过RegisterPlurality方法注册ISystem类型实例
/// </summary>
/// <param name="system">要注册的系统实例</param>
public void RegisterSystem(ISystem system)
{
RegisterPlurality(system);
}
/// <summary>
/// 注册指定泛型类型的服务实例
/// </summary>
/// <typeparam name="T">服务类型</typeparam>
/// <param name="instance">要注册的实例对象</param>
/// <exception cref="InvalidOperationException">当容器已冻结时抛出</exception>
public void Register<T>(T instance)
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
GetServicesUnsafe.AddSingleton(typeof(T), instance!);
_registeredInstances.Add(instance!);
_logger.Debug($"Registered: {typeof(T).Name}");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册指定类型的服务实例
/// </summary>
/// <param name="type">服务类型</param>
/// <param name="instance">要注册的实例对象</param>
/// <exception cref="InvalidOperationException">当容器已冻结时抛出</exception>
public void Register(Type type, object instance)
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
GetServicesUnsafe.AddSingleton(type, instance);
_registeredInstances.Add(instance);
_logger.Debug($"Registered: {type.Name}");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册工厂方法来创建服务实例
/// 通过委托函数动态创建服务实例,支持依赖注入
/// </summary>
/// <typeparam name="TService">服务类型</typeparam>
/// <param name="factory">创建服务实例的工厂委托函数接收IServiceProvider参数</param>
public void RegisterFactory<TService>(
Func<IServiceProvider, TService> factory) where TService : class
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
GetServicesUnsafe.AddSingleton(factory);
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 注册中介行为管道
/// 用于配置Mediator框架的行为拦截和处理逻辑
/// </summary>
/// <typeparam name="TBehavior">行为类型,必须是引用类型</typeparam>
public void RegisterMediatorBehavior<TBehavior>() where TBehavior : class
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
GetServicesUnsafe.AddSingleton(
typeof(IPipelineBehavior<,>),
typeof(TBehavior)
);
_logger.Debug($"Mediator behavior registered: {typeof(TBehavior).Name}");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 配置服务
/// </summary>
/// <param name="configurator">服务配置委托</param>
public void ExecuteServicesHook(Action<IServiceCollection>? configurator = null)
{
_lock.EnterWriteLock();
try
{
ThrowIfFrozen();
configurator?.Invoke(GetServicesUnsafe);
}
finally
{
_lock.ExitWriteLock();
}
}
#endregion
#region Get
/// <summary>
/// 获取指定泛型类型的服务实例
/// 返回第一个匹配的注册实例如果不存在则返回null
/// </summary>
/// <typeparam name="T">服务类型</typeparam>
/// <returns>服务实例或null</returns>
public T? Get<T>() where T : class
{
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中查找已注册的实例
var serviceType = typeof(T);
var descriptor = GetServicesUnsafe.FirstOrDefault(s =>
s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType));
if (descriptor?.ImplementationInstance is T instance)
{
return instance;
}
// 在未冻结状态下无法调用工厂方法或创建实例返回null
return null;
}
var result = _provider!.GetService<T>();
_logger.Debug(result != null
? $"Retrieved instance: {typeof(T).Name}"
: $"No instance found for type: {typeof(T).Name}");
return result;
}
finally
{
_lock.ExitReadLock();
}
}
/// <summary>
/// 获取指定类型的服务实例
/// 返回第一个匹配的注册实例如果不存在则返回null
/// </summary>
/// <param name="type">服务类型</param>
/// <returns>服务实例或null</returns>
public object? Get(Type type)
{
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中查找已注册的实例
var descriptor =
GetServicesUnsafe.FirstOrDefault(s =>
s.ServiceType == type || type.IsAssignableFrom(s.ServiceType));
return descriptor?.ImplementationInstance;
}
var result = _provider!.GetService(type);
_logger.Debug(result != null
? $"Retrieved instance: {type.Name}"
: $"No instance found for type: {type.Name}");
return result;
}
finally
{
_lock.ExitReadLock();
}
}
/// <summary>
/// 获取指定泛型类型的必需服务实例
/// 必须存在且唯一,否则抛出异常
/// </summary>
/// <typeparam name="T">服务类型</typeparam>
/// <returns>唯一的服务实例</returns>
/// <exception cref="InvalidOperationException">当实例不存在或多于一个时抛出</exception>
public T GetRequired<T>() where T : class
{
var list = GetAll<T>();
switch (list.Count)
{
case 0:
var notFoundMsg = $"No instance registered for {typeof(T).Name}";
_logger.Error(notFoundMsg);
throw new InvalidOperationException(notFoundMsg);
case 1:
_logger.Debug($"Retrieved required instance: {typeof(T).Name}");
return list[0];
default:
var multipleMsg = $"Multiple instances registered for {typeof(T).Name}";
_logger.Error(multipleMsg);
throw new InvalidOperationException(multipleMsg);
}
}
/// <summary>
/// 获取指定类型的必需服务实例
/// 必须存在且唯一,否则抛出异常
/// </summary>
/// <param name="type">服务类型</param>
/// <returns>唯一的服务实例</returns>
/// <exception cref="InvalidOperationException">当实例不存在或多于一个时抛出</exception>
public object GetRequired(Type type)
{
var list = GetAll(type);
switch (list.Count)
{
case 0:
var notFoundMsg = $"No instance registered for {type.Name}";
_logger.Error(notFoundMsg);
throw new InvalidOperationException(notFoundMsg);
case 1:
_logger.Debug($"Retrieved required instance: {type.Name}");
return list[0];
default:
var multipleMsg = $"Multiple instances registered for {type.Name}";
_logger.Error(multipleMsg);
throw new InvalidOperationException(multipleMsg);
}
}
/// <summary>
/// 获取指定泛型类型的所有服务实例
/// </summary>
/// <typeparam name="T">服务类型</typeparam>
/// <returns>只读的服务实例列表</returns>
public IReadOnlyList<T> GetAll<T>() where T : class
{
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中获取已注册的实例
var serviceType = typeof(T);
var registeredServices = GetServicesUnsafe
.Where(s => s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType)).ToList();
var result = new List<T>();
foreach (var descriptor in registeredServices)
{
if (descriptor.ImplementationInstance is T instance)
{
result.Add(instance);
}
else if (descriptor.ImplementationFactory != null)
{
// 在未冻结状态下无法调用工厂方法,跳过
}
else if (descriptor.ImplementationType != null)
{
// 在未冻结状态下无法创建实例,跳过
}
}
return result;
}
var services = _provider!.GetServices<T>().ToList();
_logger.Debug($"Retrieved {services.Count} instances of {typeof(T).Name}");
return services;
}
finally
{
_lock.ExitReadLock();
}
}
/// <summary>
/// 获取指定类型的所有服务实例
/// </summary>
/// <param name="type">服务类型</param>
/// <returns>只读的服务实例列表</returns>
/// <exception cref="InvalidOperationException">当容器未冻结时抛出</exception>
public IReadOnlyList<object> GetAll(Type type)
{
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中获取已注册的实例
var registeredServices = GetServicesUnsafe
.Where(s => s.ServiceType == type || type.IsAssignableFrom(s.ServiceType))
.ToList();
var result = new List<object>();
foreach (var descriptor in registeredServices)
{
if (descriptor.ImplementationInstance != null)
{
result.Add(descriptor.ImplementationInstance);
}
else if (descriptor.ImplementationFactory != null)
{
// 在未冻结状态下无法调用工厂方法,跳过
}
else if (descriptor.ImplementationType != null)
{
// 在未冻结状态下无法创建实例,跳过
}
}
return result;
}
var services = _provider!.GetServices(type).ToList();
_logger.Debug($"Retrieved {services.Count} instances of {type.Name}");
return services.Where(o => o != null).Cast<object>().ToList();
}
finally
{
_lock.ExitReadLock();
}
}
/// <summary>
/// 获取并排序指定泛型类型的所有服务实例
/// 主要用于系统调度场景
/// </summary>
/// <typeparam name="T">服务类型</typeparam>
/// <param name="comparison">比较委托,用于定义排序规则</param>
/// <returns>排序后的只读服务实例列表</returns>
public IReadOnlyList<T> GetAllSorted<T>(Comparison<T> comparison) where T : class
{
var list = GetAll<T>().ToList();
list.Sort(comparison);
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;
// 使用 OrderBy 确保稳定排序(相同优先级保持原有顺序)
return services
.Select((service, index) => new { Service = service, Index = index })
.OrderBy(x =>
{
var priority = x.Service is IPrioritized p ? p.Priority : 0;
return (priority, x.Index); // 先按优先级,再按索引
})
.Select(x => x.Service)
.ToList();
}
#endregion
#region Utility
/// <summary>
/// 检查容器中是否包含指定泛型类型的实例
/// 根据容器状态选择不同的检查策略
/// </summary>
/// <typeparam name="T">要检查的类型</typeparam>
/// <returns>true表示包含该类型实例false表示不包含</returns>
public bool Contains<T>() where T : class
{
_lock.EnterReadLock();
try
{
if (_provider == null)
return GetServicesUnsafe.Any(s => s.ServiceType == typeof(T));
return _provider.GetService<T>() != null;
}
finally
{
_lock.ExitReadLock();
}
}
/// <summary>
/// 判断容器中是否包含某个具体的实例对象
/// 通过已注册实例集合进行快速查找
/// </summary>
/// <param name="instance">要检查的实例对象</param>
/// <returns>true表示包含该实例false表示不包含</returns>
public bool ContainsInstance(object instance)
{
_lock.EnterReadLock();
try
{
return _registeredInstances.Contains(instance);
}
finally
{
_lock.ExitReadLock();
}
}
/// <summary>
/// 清空容器中的所有实例和服务注册
/// 只有在容器未冻结状态下才能执行清空操作
/// </summary>
public void Clear()
{
_lock.EnterWriteLock();
try
{
// 冻结的容器不允许清空操作
if (_frozen)
{
_logger.Warn("Cannot clear frozen container");
return;
}
GetServicesUnsafe.Clear();
_registeredInstances.Clear();
_provider = null;
_logger.Info("Container cleared");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 冻结容器并构建ServiceProvider
/// 冻结后容器变为只读状态,不能再注册新服务
/// </summary>
public void Freeze()
{
_lock.EnterWriteLock();
try
{
// 防止重复冻结
if (_frozen)
{
_logger.Warn("Container already frozen");
return;
}
_provider = GetServicesUnsafe.BuildServiceProvider();
_frozen = true;
_logger.Info("IOC Container frozen - ServiceProvider built");
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// 获取底层的服务集合
/// 提供对内部IServiceCollection的访问权限用于高级配置和自定义操作
/// </summary>
/// <returns>底层的IServiceCollection实例</returns>
public IServiceCollection GetServicesUnsafe { get; } = serviceCollection ?? new ServiceCollection();
/// <summary>
/// 创建一个新的服务作用域
/// 作用域内的 Scoped 服务将共享同一实例
/// </summary>
/// <returns>服务作用域实例</returns>
/// <exception cref="InvalidOperationException">当容器未冻结时抛出</exception>
public IServiceScope CreateScope()
{
_lock.EnterReadLock();
try
{
// 在锁内检查,避免竞态条件
if (!_frozen || _provider == null)
{
const string errorMsg = "Cannot create scope before container is frozen";
_logger.Error(errorMsg);
throw new InvalidOperationException(errorMsg);
}
var scope = _provider.CreateScope();
_logger.Debug("Service scope created");
return scope;
}
finally
{
_lock.ExitReadLock();
}
}
#endregion
}