refactor(ioc): 重构IoC容器核心数据结构

- 将_instances字典的值类型从List<object>改为HashSet<object>
- 新增_objects集合用于跟踪所有已注册的对象实例
- 修改RegisterSingleton方法实现,添加容器冻结检查
- 优化RegisterInternal方法,避免重复添加相同实例
- 更新GetInstance和GetInstances方法的内部实现逻辑
- 调整Contains和Clear方法以适配新的数据结构
- 新增ContainsInstance方法用于查询具体实例是否存在
This commit is contained in:
GwWuYou 2025-12-18 22:27:26 +08:00
parent 1d2847ed5f
commit f2159065fc

View File

@ -7,11 +7,21 @@ namespace GFramework.Core.ioc;
/// </summary>
public class IocContainer
{
#region Core
/// <summary>
/// 核心存储结构:
/// 一个 Type 对应 0~N 个实例
/// 存储所有已注册对象实例的集合,用于跟踪和管理容器中的所有对象
/// 使用HashSet确保对象唯一性避免重复注册同一实例
/// </summary>
private readonly Dictionary<Type, List<object>> _instances = new();
private readonly HashSet<object> _objects = [];
/// <summary>
/// 类型索引字典,用于快速查找指定类型的所有实例
/// 键为类型对象,值为该类型对应的所有实例集合
/// </summary>
private readonly Dictionary<Type, HashSet<object>> _typeIndex = new();
#endregion
#region Lock
@ -38,7 +48,7 @@ public class IocContainer
#region Register
/// <summary>
/// 注册单例(强语义)
/// 注册单例
/// 一个类型只允许一个实例
/// </summary>
/// <typeparam name="T">要注册为单例的类型</typeparam>
@ -51,13 +61,16 @@ public class IocContainer
_lock.EnterWriteLock();
try
{
if (_instances.TryGetValue(type, out var list) && list.Count > 0)
if (_frozen)
throw new InvalidOperationException("IocContainer is frozen");
if (_typeIndex.TryGetValue(type, out var set) && set.Count > 0)
{
throw new InvalidOperationException(
$"Singleton already registered for type: {type.Name}");
}
_instances[type] = [instance!];
RegisterInternal(type, instance!);
}
finally
{
@ -105,20 +118,19 @@ public class IocContainer
{
if (_frozen)
throw new InvalidOperationException("IocContainer is frozen");
// 如果该类型还没有对应的实例列表,则创建一个新的列表
if (!_instances.TryGetValue(type, out var list))
_objects.Add(instance);
if (!_typeIndex.TryGetValue(type, out var set))
{
list = [];
_instances[type] = list;
set = [];
_typeIndex[type] = set;
}
// 避免重复添加相同的实例
if (!list.Contains(instance))
{
list.Add(instance);
}
set.Add(instance);
}
/// <summary>
/// 注册系统实例,将其绑定到其所有实现的接口上
/// </summary>
@ -184,9 +196,9 @@ public class IocContainer
_lock.EnterReadLock();
try
{
if (_instances.TryGetValue(typeof(T), out var list) && list.Count > 0)
if (_typeIndex.TryGetValue(typeof(T), out var set) && set.Count > 0)
{
return list[0] as T;
return set.First() as T;
}
return null;
@ -228,8 +240,8 @@ public class IocContainer
_lock.EnterReadLock();
try
{
return _instances.TryGetValue(typeof(T), out var list)
? list.Cast<T>().ToList() // 快照
return _typeIndex.TryGetValue(typeof(T), out var set)
? set.Cast<T>().ToList() // 快照
: Array.Empty<T>();
}
finally
@ -267,7 +279,7 @@ public class IocContainer
_lock.EnterReadLock();
try
{
return _instances.ContainsKey(typeof(T));
return _typeIndex.TryGetValue(typeof(T), out var set) && set.Count > 0;
}
finally
{
@ -280,11 +292,11 @@ public class IocContainer
/// </summary>
public void Clear()
{
// 获取写锁以确保线程安全的清空操作
_lock.EnterWriteLock();
try
{
_instances.Clear();
_objects.Clear();
_typeIndex.Clear();
}
finally
{
@ -292,6 +304,25 @@ public class IocContainer
}
}
/// <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>