mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 19:03:29 +08:00
feat(ioc): 替换自定义IoC容器为Microsoft.Extensions.DependencyInjection
- 移除原有的IocContainer实现 - 添加MicrosoftDiContainer作为Microsoft.Extensions.DependencyInjection的适配器 - 修改ArchitectureServices使用MicrosoftDiContainer替代IocContainer - 更新所有相关测试类使用MicrosoftDiContainer - 添加Mediator和Microsoft.Extensions.DependencyInjection包引用 - 扩展IIocContainer接口支持更多注册方法 - 在架构初始化中添加Mediator服务注册
This commit is contained in:
parent
68d292dc64
commit
55ec42a670
@ -25,5 +25,6 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mediator.Abstractions" Version="3.0.1"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using GFramework.Core.Abstractions.rule;
|
||||
using GFramework.Core.Abstractions.system;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace GFramework.Core.Abstractions.ioc;
|
||||
|
||||
@ -19,6 +20,14 @@ public interface IIocContainer : IContextAware
|
||||
/// <exception cref="InvalidOperationException">当该类型已经注册过单例时抛出异常</exception>
|
||||
void RegisterSingleton<T>(T instance);
|
||||
|
||||
/// <summary>
|
||||
/// 注册单例服务,指定服务类型和实现类型
|
||||
/// 创建单例实例并在容器中注册
|
||||
/// </summary>
|
||||
/// <typeparam name="TService">服务接口或基类类型</typeparam>
|
||||
/// <typeparam name="TImpl">具体的实现类型</typeparam>
|
||||
void RegisterSingleton<TService, TImpl>()
|
||||
where TImpl : class, TService where TService : class;
|
||||
|
||||
/// <summary>
|
||||
/// 注册多个实例
|
||||
@ -47,6 +56,14 @@ public interface IIocContainer : IContextAware
|
||||
/// <param name="instance">要注册的实例对象</param>
|
||||
void Register(Type type, object instance);
|
||||
|
||||
/// <summary>
|
||||
/// 注册工厂方法来创建服务实例
|
||||
/// 通过委托函数动态创建服务实例
|
||||
/// </summary>
|
||||
/// <typeparam name="TService">服务类型</typeparam>
|
||||
/// <param name="factory">创建服务实例的工厂委托函数</param>
|
||||
void RegisterFactory<TService>(Func<IServiceProvider, TService> factory);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Methods
|
||||
@ -117,7 +134,7 @@ public interface IIocContainer : IContextAware
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要检查的类型</typeparam>
|
||||
/// <returns>如果容器中包含指定类型的实例则返回true,否则返回false</returns>
|
||||
bool Contains<T>();
|
||||
bool Contains<T>() where T : class;
|
||||
|
||||
/// <summary>
|
||||
/// 判断容器中是否包含某个具体的实例对象
|
||||
@ -133,8 +150,16 @@ public interface IIocContainer : IContextAware
|
||||
|
||||
/// <summary>
|
||||
/// 冻结容器,防止后续修改
|
||||
/// 调用此方法后,容器将变为只读状态,不能再注册新的服务实例
|
||||
/// </summary>
|
||||
void Freeze();
|
||||
|
||||
/// <summary>
|
||||
/// 获取底层的服务集合
|
||||
/// 提供对内部IServiceCollection的访问权限,用于高级配置和自定义操作
|
||||
/// </summary>
|
||||
/// <returns>底层的IServiceCollection实例</returns>
|
||||
IServiceCollection Services { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -46,13 +46,13 @@ public class ArchitectureContextTests
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
// 初始化 LoggerFactoryResolver 以支持 IocContainer
|
||||
// 初始化 LoggerFactoryResolver 以支持 MicrosoftDiContainer
|
||||
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
|
||||
|
||||
_container = new IocContainer();
|
||||
_container = new MicrosoftDiContainer();
|
||||
|
||||
// 直接初始化 logger 字段
|
||||
var loggerField = typeof(IocContainer).GetField("_logger",
|
||||
var loggerField = typeof(MicrosoftDiContainer).GetField("_logger",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
loggerField?.SetValue(_container,
|
||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(ArchitectureContextTests)));
|
||||
@ -75,7 +75,7 @@ public class ArchitectureContextTests
|
||||
}
|
||||
|
||||
private ArchitectureContext? _context;
|
||||
private IocContainer? _container;
|
||||
private MicrosoftDiContainer? _container;
|
||||
private EventBus? _eventBus;
|
||||
private CommandExecutor? _commandBus;
|
||||
private QueryExecutor? _queryBus;
|
||||
|
||||
@ -59,7 +59,7 @@ public class ArchitectureServicesTests
|
||||
public void Container_Should_Be_Instance_Of_IocContainer()
|
||||
{
|
||||
Assert.That(_services!.Container, Is.InstanceOf<IIocContainer>());
|
||||
Assert.That(_services.Container, Is.InstanceOf<IocContainer>());
|
||||
Assert.That(_services.Container, Is.InstanceOf<MicrosoftDiContainer>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -218,7 +218,7 @@ public class ArchitectureServicesTests
|
||||
|
||||
public class TestArchitectureContextV3 : IArchitectureContext
|
||||
{
|
||||
private readonly IocContainer _container = new();
|
||||
private readonly MicrosoftDiContainer _container = new();
|
||||
private readonly DefaultEnvironment _environment = new();
|
||||
public int Id { get; init; }
|
||||
|
||||
|
||||
@ -229,7 +229,7 @@ public class TestArchitecture : Architecture
|
||||
/// </summary>
|
||||
public class TestArchitectureContext : IArchitectureContext
|
||||
{
|
||||
private readonly IocContainer _container = new();
|
||||
private readonly MicrosoftDiContainer _container = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取依赖注入容器
|
||||
|
||||
@ -32,7 +32,7 @@ public class AbstractAsyncCommandTests
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_container = new IocContainer();
|
||||
_container = new MicrosoftDiContainer();
|
||||
_container.RegisterPlurality(new EventBus());
|
||||
_container.RegisterPlurality(new CommandExecutor());
|
||||
_container.RegisterPlurality(new QueryExecutor());
|
||||
@ -42,7 +42,7 @@ public class AbstractAsyncCommandTests
|
||||
}
|
||||
|
||||
private ArchitectureContext _context = null!;
|
||||
private IocContainer _container = null!;
|
||||
private MicrosoftDiContainer _container = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 测试异步命令无返回值版本的基础实现
|
||||
|
||||
@ -10,7 +10,7 @@ namespace GFramework.Core.Tests.ioc;
|
||||
/// 测试 IoC 容器功能的单元测试类
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class IocContainerTests
|
||||
public class MicrosoftDiContainerTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 在每个测试方法执行前进行设置
|
||||
@ -18,18 +18,18 @@ public class IocContainerTests
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
// 初始化 LoggerFactoryResolver 以支持 IocContainer
|
||||
// 初始化 LoggerFactoryResolver 以支持 MicrosoftDiContainer
|
||||
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
|
||||
_container = new IocContainer();
|
||||
_container = new MicrosoftDiContainer();
|
||||
|
||||
// 直接初始化 logger 字段
|
||||
var loggerField = typeof(IocContainer).GetField("_logger",
|
||||
var loggerField = typeof(MicrosoftDiContainer).GetField("_logger",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
loggerField?.SetValue(_container,
|
||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(IocContainer)));
|
||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(MicrosoftDiContainer)));
|
||||
}
|
||||
|
||||
private IocContainer _container = null!;
|
||||
private MicrosoftDiContainer _container = null!;
|
||||
private readonly Dictionary<Type, object> _mockContextServices = new();
|
||||
|
||||
/// <summary>
|
||||
@ -30,7 +30,7 @@ public class AbstractAsyncQueryTests
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_container = new IocContainer();
|
||||
_container = new MicrosoftDiContainer();
|
||||
_container.RegisterPlurality(new EventBus());
|
||||
_container.RegisterPlurality(new CommandExecutor());
|
||||
_container.RegisterPlurality(new QueryExecutor());
|
||||
@ -40,7 +40,7 @@ public class AbstractAsyncQueryTests
|
||||
}
|
||||
|
||||
private ArchitectureContext _context = null!;
|
||||
private IocContainer _container = null!;
|
||||
private MicrosoftDiContainer _container = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 测试异步查询的基础实现
|
||||
|
||||
@ -37,14 +37,14 @@ public class StateMachineSystemTests
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
// 初始化 LoggerFactoryResolver 以支持 IocContainer
|
||||
// 初始化 LoggerFactoryResolver 以支持 MicrosoftDiContainer
|
||||
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
|
||||
|
||||
_eventBus = new EventBus();
|
||||
var container = new IocContainer();
|
||||
var container = new MicrosoftDiContainer();
|
||||
|
||||
// 直接初始化 logger 字段
|
||||
var loggerField = typeof(IocContainer).GetField("_logger",
|
||||
var loggerField = typeof(MicrosoftDiContainer).GetField("_logger",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
loggerField?.SetValue(container,
|
||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(StateMachineSystemTests)));
|
||||
|
||||
@ -30,7 +30,7 @@ public class AbstractContextUtilityTests
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_container = new IocContainer();
|
||||
_container = new MicrosoftDiContainer();
|
||||
_container.RegisterPlurality(new EventBus());
|
||||
_container.RegisterPlurality(new CommandExecutor());
|
||||
_container.RegisterPlurality(new QueryExecutor());
|
||||
@ -40,7 +40,7 @@ public class AbstractContextUtilityTests
|
||||
}
|
||||
|
||||
private ArchitectureContext _context = null!;
|
||||
private IocContainer _container = null!;
|
||||
private MicrosoftDiContainer _container = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 测试AbstractContextUtility实现IContextUtility接口
|
||||
|
||||
@ -12,5 +12,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LanguageExt.Core" Version="4.4.9"/>
|
||||
<PackageReference Include="Mediator.Abstractions" Version="3.0.1"/>
|
||||
<PackageReference Include="Mediator.SourceGenerator" Version="3.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@ -10,6 +10,7 @@ using GFramework.Core.Abstractions.utility;
|
||||
using GFramework.Core.environment;
|
||||
using GFramework.Core.extensions;
|
||||
using GFramework.Core.logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using IDisposable = GFramework.Core.Abstractions.lifecycle.IDisposable;
|
||||
|
||||
namespace GFramework.Core.architecture;
|
||||
@ -540,6 +541,9 @@ public abstract class Architecture(
|
||||
// 为服务设置上下文
|
||||
Services.SetContext(_context);
|
||||
|
||||
// 添加 Mediator
|
||||
Container.Services.AddMediator();
|
||||
|
||||
// === 用户 Init ===
|
||||
_logger.Debug("Calling user Init()");
|
||||
Init();
|
||||
|
||||
@ -47,7 +47,7 @@ public class ArchitectureServices : IArchitectureServices
|
||||
/// </summary>
|
||||
public ArchitectureServices()
|
||||
{
|
||||
Container = new IocContainer();
|
||||
Container = new MicrosoftDiContainer();
|
||||
|
||||
// 创建服务实例
|
||||
_eventBus = new EventBus();
|
||||
|
||||
@ -1,452 +0,0 @@
|
||||
using GFramework.Core.Abstractions.ioc;
|
||||
using GFramework.Core.Abstractions.logging;
|
||||
using GFramework.Core.Abstractions.system;
|
||||
using GFramework.Core.logging;
|
||||
using GFramework.Core.rule;
|
||||
|
||||
namespace GFramework.Core.ioc;
|
||||
|
||||
/// <summary>
|
||||
/// IOC容器类,用于管理对象的注册和获取
|
||||
/// </summary>
|
||||
public class IocContainer : ContextAwareBase, IIocContainer
|
||||
{
|
||||
#region Lock
|
||||
|
||||
/// <summary>
|
||||
/// 读写锁对象,用于控制多线程环境下对共享资源的访问
|
||||
/// 使用ReaderWriterLockSlim提供高效的读写锁定机制
|
||||
/// 配置为不支持递归锁,避免死锁风险
|
||||
/// </summary>
|
||||
private readonly ReaderWriterLockSlim _lock = new(LockRecursionPolicy.NoRecursion);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Flag
|
||||
|
||||
/// <summary>
|
||||
/// 冻结标志位,用于标识对象是否已被冻结
|
||||
/// true表示对象已冻结,不可修改;false表示对象可正常修改
|
||||
/// </summary>
|
||||
private volatile bool _frozen;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Core
|
||||
|
||||
/// <summary>
|
||||
/// 存储所有已注册对象实例的集合,用于跟踪和管理容器中的所有对象
|
||||
/// 使用HashSet确保对象唯一性,避免重复注册同一实例
|
||||
/// </summary>
|
||||
private readonly HashSet<object> _objects = [];
|
||||
|
||||
/// <summary>
|
||||
/// 类型索引字典,用于快速查找指定类型的所有实例
|
||||
/// 键为类型对象,值为该类型对应的所有实例集合
|
||||
/// </summary>
|
||||
private readonly Dictionary<Type, HashSet<object>> _typeIndex = new();
|
||||
|
||||
private ILogger _logger = null!;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Register
|
||||
|
||||
/// <summary>
|
||||
/// 当上下文准备就绪时调用此方法,用于初始化日志记录器。
|
||||
/// </summary>
|
||||
protected override void OnContextReady()
|
||||
{
|
||||
// 创建日志记录器实例,并将其赋值给_logger字段
|
||||
_logger =
|
||||
LoggerFactoryResolver.Provider.CreateLogger(nameof(IocContainer));
|
||||
}
|
||||
|
||||
|
||||
/// <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
|
||||
{
|
||||
// 检查容器是否已被冻结
|
||||
if (_frozen)
|
||||
{
|
||||
var errorMsg = "IocContainer is frozen";
|
||||
_logger.Error(errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
|
||||
// 检查该类型是否已经注册过单例
|
||||
if (_typeIndex.TryGetValue(type, out var set) && set.Count > 0)
|
||||
{
|
||||
var errorMsg = $"Singleton already registered for type: {type.Name}";
|
||||
_logger.Error(errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
|
||||
RegisterInternal(type, instance!);
|
||||
_logger.Debug($"Singleton registered: {type.Name}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册多个实例
|
||||
/// 将实例注册到其实现的所有接口和具体类型上
|
||||
/// </summary>
|
||||
/// <param name="instance">要注册的实例</param>
|
||||
public void RegisterPlurality(object instance)
|
||||
{
|
||||
var concreteType = instance.GetType();
|
||||
var interfaces = concreteType.GetInterfaces();
|
||||
|
||||
_lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
// 注册具体类型
|
||||
RegisterInternal(concreteType, instance);
|
||||
|
||||
// 注册所有接口类型
|
||||
foreach (var itf in interfaces) RegisterInternal(itf, instance);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在内部字典中注册指定类型和实例的映射关系
|
||||
/// </summary>
|
||||
/// <param name="type">要注册的类型</param>
|
||||
/// <param name="instance">要注册的实例</param>
|
||||
private void RegisterInternal(Type type, object instance)
|
||||
{
|
||||
if (_frozen)
|
||||
{
|
||||
const string errorMsg = "IocContainer is frozen";
|
||||
_logger.Error(errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
|
||||
_objects.Add(instance);
|
||||
|
||||
if (!_typeIndex.TryGetValue(type, out var set))
|
||||
{
|
||||
set = [];
|
||||
_typeIndex[type] = set;
|
||||
}
|
||||
|
||||
set.Add(instance);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 注册系统实例,将其绑定到其所有实现的接口上
|
||||
/// </summary>
|
||||
/// <param name="system">系统实例对象</param>
|
||||
public void RegisterSystem(ISystem system)
|
||||
{
|
||||
RegisterPlurality(system);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 注册指定类型的实例到容器中
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要注册的实例类型</typeparam>
|
||||
/// <param name="instance">要注册的实例对象,不能为null</param>
|
||||
public void Register<T>(T instance)
|
||||
{
|
||||
// 获取写锁以确保线程安全
|
||||
_lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
RegisterInternal(typeof(T), instance!);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 释放写锁
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册指定类型的实例到容器中
|
||||
/// </summary>
|
||||
/// <param name="type">要注册的实例类型</param>
|
||||
/// <param name="instance">要注册的实例对象</param>
|
||||
public void Register(Type type, object instance)
|
||||
{
|
||||
// 获取写锁以确保线程安全
|
||||
_lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
RegisterInternal(type, instance);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 释放写锁
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个实例(通常用于具体类型)
|
||||
/// 如果存在多个,只返回第一个
|
||||
/// </summary>
|
||||
/// <typeparam name="T">期望获取的实例类型</typeparam>
|
||||
/// <returns>找到的第一个实例;如果未找到则返回 null</returns>
|
||||
public T? Get<T>() where T : class
|
||||
{
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (_typeIndex.TryGetValue(typeof(T), out var set) && set.Count > 0)
|
||||
{
|
||||
var result = set.First() as T;
|
||||
_logger.Debug($"Retrieved instance: {typeof(T).Name}");
|
||||
return result;
|
||||
}
|
||||
|
||||
_logger.Debug($"No instance found for type: {typeof(T).Name}");
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的单个实例
|
||||
/// 如果存在多个,只返回第一个
|
||||
/// </summary>
|
||||
/// <param name="type">期望获取的实例类型</param>
|
||||
/// <returns>找到的第一个实例;如果未找到则返回 null</returns>
|
||||
public object? Get(Type type)
|
||||
{
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (_typeIndex.TryGetValue(type, out var set) && set.Count > 0)
|
||||
{
|
||||
var result = set.First();
|
||||
_logger.Debug($"Retrieved instance: {type.Name}");
|
||||
return result;
|
||||
}
|
||||
|
||||
_logger.Debug($"No instance found for type: {type.Name}");
|
||||
return null;
|
||||
}
|
||||
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
|
||||
{
|
||||
return _typeIndex.TryGetValue(typeof(T), out var set)
|
||||
? set.Cast<T>().ToList() // 快照
|
||||
: Array.Empty<T>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的所有实例
|
||||
/// </summary>
|
||||
/// <param name="type">期望获取的实例类型</param>
|
||||
/// <returns>所有符合条件的实例列表;如果没有则返回空数组</returns>
|
||||
public IReadOnlyList<object> GetAll(Type type)
|
||||
{
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
return _typeIndex.TryGetValue(type, out var set)
|
||||
? set.ToList() // 快照
|
||||
: Array.Empty<object>();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
|
||||
/// <summary>
|
||||
/// 检查容器中是否包含指定类型的实例
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要检查的类型</typeparam>
|
||||
/// <returns>如果容器中包含指定类型的实例则返回true,否则返回false</returns>
|
||||
public bool Contains<T>()
|
||||
{
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
return _typeIndex.TryGetValue(typeof(T), out var set) && set.Count > 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空容器中的所有实例
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_objects.Clear();
|
||||
_typeIndex.Clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断容器中是否包含某个具体的实例对象
|
||||
/// </summary>
|
||||
/// <param name="instance">待查询的实例对象</param>
|
||||
/// <returns>若容器中包含该实例则返回true,否则返回false</returns>
|
||||
public bool ContainsInstance(object instance)
|
||||
{
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
return _objects.Contains(instance);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 冻结容器,防止后续修改
|
||||
/// </summary>
|
||||
public void Freeze()
|
||||
{
|
||||
// 获取写锁以确保线程安全的状态修改
|
||||
_lock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_frozen = true;
|
||||
_logger.Info("IOC Container frozen - no further registrations allowed");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
516
GFramework.Core/ioc/MicrosoftDiContainer.cs
Normal file
516
GFramework.Core/ioc/MicrosoftDiContainer.cs
Normal file
@ -0,0 +1,516 @@
|
||||
using GFramework.Core.Abstractions.ioc;
|
||||
using GFramework.Core.Abstractions.logging;
|
||||
using GFramework.Core.Abstractions.system;
|
||||
using GFramework.Core.logging;
|
||||
using GFramework.Core.rule;
|
||||
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 Context Ready
|
||||
|
||||
/// <summary>
|
||||
/// 上下文准备就绪时的回调方法
|
||||
/// 初始化日志记录器实例
|
||||
/// </summary>
|
||||
protected override void OnContextReady()
|
||||
{
|
||||
_logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(MicrosoftDiContainer));
|
||||
}
|
||||
|
||||
#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 ILogger _logger = null!;
|
||||
|
||||
#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 (Services.Any(s => s.ServiceType == type))
|
||||
{
|
||||
var errorMsg = $"Singleton already registered for type: {type.Name}";
|
||||
_logger.Error(errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
|
||||
Services.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
|
||||
{
|
||||
Services.AddSingleton<TService, TImpl>();
|
||||
}
|
||||
|
||||
/// <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();
|
||||
|
||||
// 注册具体类型映射
|
||||
Services.AddSingleton(concreteType, instance);
|
||||
|
||||
// 注册所有接口类型映射(指向同一实例)
|
||||
foreach (var interfaceType in interfaces)
|
||||
{
|
||||
Services.AddSingleton(interfaceType, _ => instance);
|
||||
}
|
||||
|
||||
_registeredInstances.Add(instance);
|
||||
_logger.Debug($"Plurality 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();
|
||||
Services.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();
|
||||
Services.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)
|
||||
{
|
||||
ThrowIfFrozen();
|
||||
Services.AddSingleton(factory);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定泛型类型的服务实例
|
||||
/// 返回第一个匹配的注册实例,如果不存在则返回null
|
||||
/// </summary>
|
||||
/// <typeparam name="T">服务类型</typeparam>
|
||||
/// <returns>服务实例或null</returns>
|
||||
/// <exception cref="InvalidOperationException">当容器未冻结时抛出</exception>
|
||||
public T? Get<T>() where T : class
|
||||
{
|
||||
EnsureProvider();
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
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>
|
||||
/// <exception cref="InvalidOperationException">当容器未冻结时抛出</exception>
|
||||
public object? Get(Type type)
|
||||
{
|
||||
EnsureProvider();
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
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>
|
||||
/// <exception cref="InvalidOperationException">当容器未冻结时抛出</exception>
|
||||
public IReadOnlyList<T> GetAll<T>() where T : class
|
||||
{
|
||||
EnsureProvider();
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
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)
|
||||
{
|
||||
EnsureProvider();
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
|
||||
/// <summary>
|
||||
/// 检查容器中是否包含指定泛型类型的实例
|
||||
/// 根据容器状态选择不同的检查策略
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要检查的类型</typeparam>
|
||||
/// <returns>true表示包含该类型实例,false表示不包含</returns>
|
||||
public bool Contains<T>() where T : class
|
||||
{
|
||||
if (_provider == null)
|
||||
return Services.Any(s => s.ServiceType == typeof(T));
|
||||
|
||||
_lock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Services.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 = Services.BuildServiceProvider();
|
||||
_frozen = true;
|
||||
_logger.Info("IOC Container frozen - ServiceProvider built");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取底层的服务集合
|
||||
/// 提供对内部IServiceCollection的访问权限,用于高级配置和自定义操作
|
||||
/// </summary>
|
||||
/// <returns>底层的IServiceCollection实例</returns>
|
||||
public IServiceCollection Services { get; } = serviceCollection ?? new ServiceCollection();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// 检查容器是否已冻结,如果已冻结则抛出异常
|
||||
/// 用于保护注册操作的安全性
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">当容器已冻结时抛出</exception>
|
||||
private void ThrowIfFrozen()
|
||||
{
|
||||
if (_frozen)
|
||||
{
|
||||
const string errorMsg = "MicrosoftDiContainer is frozen";
|
||||
_logger.Error(errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保ServiceProvider已构建,如果未构建则抛出异常
|
||||
/// 用于保护获取服务操作的安全性
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">当ServiceProvider未构建时抛出</exception>
|
||||
private void EnsureProvider()
|
||||
{
|
||||
if (_provider == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Container has not been frozen yet. Call Freeze() before retrieving services.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user