using GFramework.Core.system; namespace GFramework.Core.ioc; /// /// IOC容器类,用于管理对象的注册和获取 /// public class IocContainer { #region Core /// /// 存储所有已注册对象实例的集合,用于跟踪和管理容器中的所有对象 /// 使用HashSet确保对象唯一性,避免重复注册同一实例 /// private readonly HashSet _objects = []; /// /// 类型索引字典,用于快速查找指定类型的所有实例 /// 键为类型对象,值为该类型对应的所有实例集合 /// private readonly Dictionary> _typeIndex = new(); #endregion #region Lock /// /// 读写锁对象,用于控制多线程环境下对共享资源的访问 /// 使用ReaderWriterLockSlim提供高效的读写锁定机制 /// 配置为不支持递归锁,避免死锁风险 /// private readonly ReaderWriterLockSlim _lock = new(LockRecursionPolicy.NoRecursion); #endregion #region Flag /// /// 冻结标志位,用于标识对象是否已被冻结 /// true表示对象已冻结,不可修改;false表示对象可正常修改 /// private volatile bool _frozen; #endregion #region Register /// /// 注册单例 /// 一个类型只允许一个实例 /// /// 要注册为单例的类型 /// 要注册的单例实例 /// 当该类型已经注册过单例时抛出异常 public void RegisterSingleton(T instance) { var type = typeof(T); _lock.EnterWriteLock(); try { 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}"); } RegisterInternal(type, instance!); } finally { _lock.ExitWriteLock(); } } /// /// 注册一个实例及其所有可赋值的接口类型到容器中 /// /// 实例的类型 /// 要注册的实例对象,不能为null public void RegisterPlurality(T instance) { var concreteType = instance!.GetType(); // 获取实例类型直接实现的所有接口,并筛选出可以赋值给T类型的接口 var interfaces = concreteType.GetInterfaces() .Where(typeof(T).IsAssignableFrom); _lock.EnterWriteLock(); try { // 注册具体类型 RegisterInternal(concreteType, instance); // 注册所有匹配的接口类型 foreach (var itf in interfaces) { RegisterInternal(itf, instance); } } finally { _lock.ExitWriteLock(); } } /// /// 在内部字典中注册指定类型和实例的映射关系 /// /// 要注册的类型 /// 要注册的实例 private void RegisterInternal(Type type, object instance) { if (_frozen) throw new InvalidOperationException("IocContainer is frozen"); _objects.Add(instance); if (!_typeIndex.TryGetValue(type, out var set)) { set = []; _typeIndex[type] = set; } set.Add(instance); } /// /// 注册系统实例,将其绑定到其所有实现的接口上 /// /// 系统实例对象 public void RegisterSystem(ISystem system) { RegisterPlurality(system); } /// /// 注册指定类型的实例到容器中 /// /// 要注册的实例类型 /// 要注册的实例对象,不能为null public void Register(T instance) { // 获取写锁以确保线程安全 _lock.EnterWriteLock(); try { RegisterInternal(typeof(T), instance!); } finally { // 释放写锁 _lock.ExitWriteLock(); } } /// /// 注册指定类型的实例到容器中 /// /// 要注册的实例类型 /// 要注册的实例对象 public void Register(Type type, object instance) { // 获取写锁以确保线程安全 _lock.EnterWriteLock(); try { RegisterInternal(type, instance); } finally { // 释放写锁 _lock.ExitWriteLock(); } } #endregion #region Get /// /// 获取单个实例(通常用于具体类型) /// 如果存在多个,只返回第一个 /// /// 期望获取的实例类型 /// 找到的第一个实例;如果未找到则返回 null public T? Get() where T : class { _lock.EnterReadLock(); try { if (_typeIndex.TryGetValue(typeof(T), out var set) && set.Count > 0) { return set.First() as T; } return null; } finally { _lock.ExitReadLock(); } } /// /// 获取指定类型的必需实例 /// /// 期望获取的实例类型 /// 找到的唯一实例 /// 当没有注册实例或注册了多个实例时抛出 public T GetRequired() where T : class { var list = GetAll(); // 根据实例数量进行判断和处理 return list.Count switch { 0 => throw new InvalidOperationException($"No instance registered for {typeof(T).Name}"), > 1 => throw new InvalidOperationException($"Multiple instances registered for {typeof(T).Name}"), _ => list[0] }; } /// /// 获取指定类型的所有实例(接口 / 抽象类推荐使用) /// /// 期望获取的实例类型 /// 所有符合条件的实例列表;如果没有则返回空数组 public IReadOnlyList GetAll() where T : class { _lock.EnterReadLock(); try { return _typeIndex.TryGetValue(typeof(T), out var set) ? set.Cast().ToList() // 快照 : Array.Empty(); } finally { _lock.ExitReadLock(); } } /// /// 获取并排序(系统调度专用) /// /// 期望获取的实例类型 /// 比较器委托,定义排序规则 /// 按指定方式排序后的实例列表 public IReadOnlyList GetAllSorted(Comparison comparison) where T : class { var list = GetAll().ToList(); list.Sort(comparison); return list; } #endregion #region Utility /// /// 检查容器中是否包含指定类型的实例 /// /// 要检查的类型 /// 如果容器中包含指定类型的实例则返回true,否则返回false public bool Contains() { _lock.EnterReadLock(); try { return _typeIndex.TryGetValue(typeof(T), out var set) && set.Count > 0; } finally { _lock.ExitReadLock(); } } /// /// 清空容器中的所有实例 /// public void Clear() { _lock.EnterWriteLock(); try { _objects.Clear(); _typeIndex.Clear(); } finally { _lock.ExitWriteLock(); } } /// /// 判断容器中是否包含某个具体的实例对象 /// /// 待查询的实例对象 /// 若容器中包含该实例则返回true,否则返回false public bool ContainsInstance(object instance) { _lock.EnterReadLock(); try { return _objects.Contains(instance); } finally { _lock.ExitReadLock(); } } /// /// 冻结容器,防止后续修改 /// public void Freeze() { // 获取写锁以确保线程安全的状态修改 _lock.EnterWriteLock(); try { _frozen = true; } finally { _lock.ExitWriteLock(); } } #endregion }