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