mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-25 21:34:28 +08:00
feat(ioc): 实现IOC容器线程安全与冻结机制
- 添加读写锁确保多线程环境下的访问安全 - 引入冻结标志位防止容器被意外修改 - 注册和查询方法均增加锁保护逻辑 - 新增 Freeze 方法用于锁定容器状态 - 重构注册内部逻辑并提取公共方法 - 所有公开方法添加线程安全注释说明 - [not tag]
This commit is contained in:
parent
5270a19e44
commit
1aafadc000
@ -46,6 +46,8 @@ public abstract class Architecture<T> : IArchitecture where T : Architecture<T>,
|
|||||||
foreach (var system in arch._mSystems) system.Init();
|
foreach (var system in arch._mSystems) system.Init();
|
||||||
|
|
||||||
arch._mSystems.Clear();
|
arch._mSystems.Clear();
|
||||||
|
// 冻结IOC容器,不允许 anymore
|
||||||
|
arch._mContainer.Freeze();
|
||||||
// 发送架构初始化完成事件
|
// 发送架构初始化完成事件
|
||||||
arch.SendEvent(new ArchitectureEvents.ArchitectureInitializedEvent());
|
arch.SendEvent(new ArchitectureEvents.ArchitectureInitializedEvent());
|
||||||
arch._mInited = true;
|
arch._mInited = true;
|
||||||
|
|||||||
@ -13,6 +13,28 @@ public class IocContainer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Dictionary<Type, List<object>> _instances = new();
|
private readonly Dictionary<Type, List<object>> _instances = new();
|
||||||
|
|
||||||
|
#region Lock
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读写锁对象,用于控制多线程环境下对共享资源的访问
|
||||||
|
/// 使用ReaderWriterLockSlim提供高效的读写锁定机制
|
||||||
|
/// 配置为不支持递归锁,避免死锁风险
|
||||||
|
/// </summary>
|
||||||
|
private readonly ReaderWriterLockSlim _lock = new(LockRecursionPolicy.NoRecursion);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Flag
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 冻结标志位,用于标识对象是否已被冻结
|
||||||
|
/// true表示对象已冻结,不可修改;false表示对象可正常修改
|
||||||
|
/// </summary>
|
||||||
|
private bool _frozen;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Register
|
#region Register
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -26,6 +48,9 @@ public class IocContainer
|
|||||||
{
|
{
|
||||||
var type = typeof(T);
|
var type = typeof(T);
|
||||||
|
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
if (_instances.TryGetValue(type, out var list) && list.Count > 0)
|
if (_instances.TryGetValue(type, out var list) && list.Count > 0)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
@ -34,22 +59,63 @@ public class IocContainer
|
|||||||
|
|
||||||
_instances[type] = [instance!];
|
_instances[type] = [instance!];
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册多个接口实现,并将其实例同时绑定到其所有匹配的接口上
|
/// 注册一个实例及其所有可赋值的接口类型到容器中
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">基类型或接口类型</typeparam>
|
/// <typeparam name="T">实例的类型</typeparam>
|
||||||
/// <param name="instance">具体的实例对象</param>
|
/// <param name="instance">要注册的实例对象,不能为null</param>
|
||||||
public void RegisterPlurality<T>(T instance)
|
public void RegisterPlurality<T>(T instance)
|
||||||
{
|
{
|
||||||
var concreteType = instance!.GetType();
|
var concreteType = instance!.GetType();
|
||||||
Register(concreteType, instance);
|
// 获取实例类型直接实现的所有接口,并筛选出可以赋值给T类型的接口
|
||||||
// 获取实例类型实现的所有接口,并筛选出可以赋值给T类型的接口
|
|
||||||
var interfaces = concreteType.GetInterfaces()
|
var interfaces = concreteType.GetInterfaces()
|
||||||
.Where(typeof(T).IsAssignableFrom);
|
.Where(typeof(T).IsAssignableFrom);
|
||||||
|
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 注册具体类型
|
||||||
|
RegisterInternal(concreteType, instance);
|
||||||
|
|
||||||
|
// 注册所有匹配的接口类型
|
||||||
foreach (var itf in interfaces)
|
foreach (var itf in interfaces)
|
||||||
{
|
{
|
||||||
Register(itf, instance);
|
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)
|
||||||
|
throw new InvalidOperationException("IocContainer is frozen");
|
||||||
|
// 如果该类型还没有对应的实例列表,则创建一个新的列表
|
||||||
|
if (!_instances.TryGetValue(type, out var list))
|
||||||
|
{
|
||||||
|
list = [];
|
||||||
|
_instances[type] = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 避免重复添加相同的实例
|
||||||
|
if (!list.Contains(instance))
|
||||||
|
{
|
||||||
|
list.Add(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,34 +128,44 @@ public class IocContainer
|
|||||||
RegisterPlurality(system);
|
RegisterPlurality(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册实例(自动支持多实例)
|
/// 注册指定类型的实例到容器中
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">要注册的实例的类型</typeparam>
|
/// <typeparam name="T">要注册的实例类型</typeparam>
|
||||||
/// <param name="instance">要注册的实例</param>
|
/// <param name="instance">要注册的实例对象,不能为null</param>
|
||||||
public void Register<T>(T instance)
|
public void Register<T>(T instance)
|
||||||
{
|
{
|
||||||
Register(typeof(T), instance!);
|
// 获取写锁以确保线程安全
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RegisterInternal(typeof(T), instance!);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// 释放写锁
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按指定类型注册实例
|
/// 注册指定类型的实例到容器中
|
||||||
/// (常用于 interface / base type)
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">要注册的目标类型</param>
|
/// <param name="type">要注册的实例类型</param>
|
||||||
/// <param name="instance">要注册的实例</param>
|
/// <param name="instance">要注册的实例对象</param>
|
||||||
public void Register(Type type, object instance)
|
public void Register(Type type, object instance)
|
||||||
{
|
{
|
||||||
if (!_instances.TryGetValue(type, out var list))
|
// 获取写锁以确保线程安全
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
list = [];
|
RegisterInternal(type, instance);
|
||||||
_instances[type] = list;
|
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
// 防止重复注册同一个实例
|
|
||||||
if (!list.Contains(instance))
|
|
||||||
{
|
{
|
||||||
list.Add(instance);
|
// 释放写锁
|
||||||
|
_lock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,16 +181,22 @@ public class IocContainer
|
|||||||
/// <returns>找到的第一个实例;如果未找到则返回 null</returns>
|
/// <returns>找到的第一个实例;如果未找到则返回 null</returns>
|
||||||
public T? Get<T>() where T : class
|
public T? Get<T>() where T : class
|
||||||
{
|
{
|
||||||
var type = typeof(T);
|
_lock.EnterReadLock();
|
||||||
|
try
|
||||||
// 尝试从实例字典中获取指定类型的实例列表
|
{
|
||||||
if (_instances.TryGetValue(type, out var list) && list.Count > 0)
|
if (_instances.TryGetValue(typeof(T), out var list) && list.Count > 0)
|
||||||
{
|
{
|
||||||
return list[0] as T;
|
return list[0] as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定类型的必需实例
|
/// 获取指定类型的必需实例
|
||||||
@ -143,15 +225,19 @@ public class IocContainer
|
|||||||
/// <returns>所有符合条件的实例列表;如果没有则返回空数组</returns>
|
/// <returns>所有符合条件的实例列表;如果没有则返回空数组</returns>
|
||||||
public IReadOnlyList<T> GetAll<T>() where T : class
|
public IReadOnlyList<T> GetAll<T>() where T : class
|
||||||
{
|
{
|
||||||
var type = typeof(T);
|
_lock.EnterReadLock();
|
||||||
|
try
|
||||||
if (_instances.TryGetValue(type, out var list))
|
|
||||||
{
|
{
|
||||||
return list.Cast<T>().ToList();
|
return _instances.TryGetValue(typeof(T), out var list)
|
||||||
|
? list.Cast<T>().ToList() // 快照
|
||||||
|
: Array.Empty<T>();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.Empty<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取并排序(系统调度专用)
|
/// 获取并排序(系统调度专用)
|
||||||
@ -172,22 +258,56 @@ public class IocContainer
|
|||||||
#region Utility
|
#region Utility
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否已注册指定类型
|
/// 检查容器中是否包含指定类型的实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">要检查是否注册的类型</typeparam>
|
/// <typeparam name="T">要检查的类型</typeparam>
|
||||||
/// <returns>若该类型已被注册则返回 true,否则返回 false</returns>
|
/// <returns>如果容器中包含指定类型的实例则返回true,否则返回false</returns>
|
||||||
public bool Contains<T>()
|
public bool Contains<T>()
|
||||||
|
{
|
||||||
|
_lock.EnterReadLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return _instances.ContainsKey(typeof(T));
|
return _instances.ContainsKey(typeof(T));
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清空容器
|
/// 清空容器中的所有实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
|
{
|
||||||
|
// 获取写锁以确保线程安全的清空操作
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_instances.Clear();
|
_instances.Clear();
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 冻结容器,防止后续修改
|
||||||
|
/// </summary>
|
||||||
|
public void Freeze()
|
||||||
|
{
|
||||||
|
// 获取写锁以确保线程安全的状态修改
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_frozen = true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user