feat(events): 添加事件上下文支持和线程安全改进

- 在EventBus中添加RegisterWithContext方法支持事件上下文
- 实现EventContext<T>类包装事件数据并提供处理控制
- 在PriorityEvent中添加上下文事件处理器和相关管理逻辑
- 改进事件触发机制支持普通和上下文处理器混合使用
- 优化MicrosoftDiContainer的线程安全性和并发访问
- 修复SpanExtensions中TryParseValue的返回值类型问题
- 添加全面的单元测试覆盖新功能和边界情况
This commit is contained in:
GeWuYou 2026-02-25 21:22:28 +08:00 committed by gewuyou
parent e2dca4f5a6
commit eec50ab45b
8 changed files with 647 additions and 127 deletions

View File

@ -0,0 +1,26 @@
namespace GFramework.Core.Abstractions.events;
/// <summary>
/// 事件上下文,包装事件数据并提供控制方法
/// </summary>
/// <typeparam name="T">事件数据类型</typeparam>
public class EventContext<T>(T data)
{
/// <summary>
/// 事件数据
/// </summary>
public T Data { get; } = data;
/// <summary>
/// 事件是否已被处理
/// </summary>
public bool IsHandled { get; private set; }
/// <summary>
/// 标记事件为已处理,停止后续传播(仅对 UntilHandled 模式有效)
/// </summary>
public void MarkAsHandled()
{
IsHandled = true;
}
}

View File

@ -234,4 +234,127 @@ public class EventBusPriorityTests
// Assert
Assert.That(executionOrder, Is.EqualTo(new[] { "first", "second", "third" }));
}
}
[Test]
public void UntilHandled_Should_Stop_After_MarkAsHandled()
{
// Arrange
var eventBus = new EventBus();
var executionOrder = new List<int>();
eventBus.RegisterWithContext<TestEvent>(ctx =>
{
executionOrder.Add(1);
ctx.MarkAsHandled();
}, priority: 10);
eventBus.RegisterWithContext<TestEvent>(ctx =>
{
executionOrder.Add(2); // 不应该执行
}, priority: 5);
// Act
eventBus.Send(new TestEvent(), EventPropagation.UntilHandled);
// Assert
Assert.That(executionOrder, Is.EqualTo(new[] { 1 }));
}
[Test]
public void UntilHandled_Should_Execute_All_If_Not_Handled()
{
// Arrange
var eventBus = new EventBus();
var executionOrder = new List<int>();
eventBus.RegisterWithContext<TestEvent>(ctx => executionOrder.Add(1), priority: 10);
eventBus.RegisterWithContext<TestEvent>(ctx => executionOrder.Add(2), priority: 5);
// Act
eventBus.Send(new TestEvent(), EventPropagation.UntilHandled);
// Assert
Assert.That(executionOrder, Is.EqualTo(new[] { 1, 2 }));
}
[Test]
public void RegisterWithContext_Should_Receive_Event_Data()
{
// Arrange
var eventBus = new EventBus();
string? receivedMessage = null;
eventBus.RegisterWithContext<TestEvent>(ctx => { receivedMessage = ctx.Data.Message; });
// Act
eventBus.Send(new TestEvent { Message = "Hello" }, EventPropagation.All);
// Assert
Assert.That(receivedMessage, Is.EqualTo("Hello"));
}
[Test]
public void UntilHandled_Should_Respect_Priority_Order()
{
// Arrange
var eventBus = new EventBus();
var executionOrder = new List<int>();
eventBus.RegisterWithContext<TestEvent>(ctx => executionOrder.Add(1), priority: 1);
eventBus.RegisterWithContext<TestEvent>(ctx =>
{
executionOrder.Add(3);
ctx.MarkAsHandled();
}, priority: 3);
eventBus.RegisterWithContext<TestEvent>(ctx => executionOrder.Add(2), priority: 2);
// Act
eventBus.Send(new TestEvent(), EventPropagation.UntilHandled);
// Assert
Assert.That(executionOrder, Is.EqualTo(new[] { 3 }));
}
[Test]
public void Handler_Can_Unregister_Itself_Without_Exception()
{
// Arrange
var eventBus = new EventBus();
var executionCount = 0;
IUnRegister? unregister = null;
unregister = eventBus.Register<TestEvent>(_ =>
{
executionCount++;
unregister?.UnRegister();
}, priority: 1);
// Act & Assert
Assert.DoesNotThrow(() => eventBus.Send(new TestEvent(), EventPropagation.All));
Assert.That(executionCount, Is.EqualTo(1));
// 第二次触发不应执行
eventBus.Send(new TestEvent(), EventPropagation.All);
Assert.That(executionCount, Is.EqualTo(1));
}
[Test]
public void Concurrent_Trigger_And_Register_Should_Be_Thread_Safe()
{
// Arrange
var eventBus = new EventBus();
var counter = 0;
eventBus.Register<TestEvent>(_ => Interlocked.Increment(ref counter), priority: 1);
// Act
var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
{
eventBus.Send(new TestEvent(), EventPropagation.All);
eventBus.Register<TestEvent>(_ => { }, priority: 1);
})).ToArray();
// Assert
Assert.DoesNotThrow(() => Task.WaitAll(tasks));
Assert.That(counter, Is.GreaterThan(0));
}
}

View File

@ -0,0 +1,165 @@
using GFramework.Core.Abstractions.events;
using GFramework.Core.events;
using NUnit.Framework;
namespace GFramework.Core.Tests.events;
/// <summary>
/// 测试 PriorityEvent 的线程安全性和边界情况
/// </summary>
[TestFixture]
public class PriorityEventTests
{
[Test]
public void Trigger_Should_Not_Throw_When_Handler_Unregisters_Itself()
{
// Arrange
var evt = new PriorityEvent<int>();
IUnRegister? unregister = null;
unregister = evt.Register(x => { unregister?.UnRegister(); });
// Act & Assert
Assert.DoesNotThrow(() => evt.Trigger(42));
}
[Test]
public void Trigger_Should_Be_Thread_Safe()
{
// Arrange
var evt = new PriorityEvent<int>();
var counter = 0;
evt.Register(x => Interlocked.Increment(ref counter));
// Act
var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
{
evt.Trigger(1);
evt.Register(x => { });
})).ToArray();
// Assert
Assert.DoesNotThrow(() => Task.WaitAll(tasks));
}
[Test]
public void Multiple_Handlers_Unregistering_During_Trigger_Should_Not_Throw()
{
// Arrange
var evt = new PriorityEvent<int>();
var unregisters = new List<IUnRegister>();
for (int i = 0; i < 10; i++)
{
var index = i;
var unreg = evt.Register(x =>
{
if (index % 2 == 0)
{
unregisters[index].UnRegister();
}
});
unregisters.Add(unreg);
}
// Act & Assert
Assert.DoesNotThrow(() => evt.Trigger(1));
}
[Test]
public void Context_Handler_Should_Receive_Correct_Data()
{
// Arrange
var evt = new PriorityEvent<string>();
string? receivedData = null;
evt.RegisterWithContext(ctx => { receivedData = ctx.Data; });
// Act
evt.Trigger("test data", EventPropagation.All);
// Assert
Assert.That(receivedData, Is.EqualTo("test data"));
}
[Test]
public void Context_Handler_MarkAsHandled_Should_Stop_UntilHandled_Propagation()
{
// Arrange
var evt = new PriorityEvent<int>();
var executionOrder = new List<int>();
evt.RegisterWithContext(ctx =>
{
executionOrder.Add(1);
ctx.MarkAsHandled();
}, priority: 10);
evt.RegisterWithContext(ctx => { executionOrder.Add(2); }, priority: 5);
// Act
evt.Trigger(42, EventPropagation.UntilHandled);
// Assert
Assert.That(executionOrder, Is.EqualTo(new[] { 1 }));
}
[Test]
public void Mixed_Normal_And_Context_Handlers_Should_Work_Together()
{
// Arrange
var evt = new PriorityEvent<int>();
var executionOrder = new List<string>();
evt.Register(x => executionOrder.Add("normal"), priority: 5);
evt.RegisterWithContext(ctx => executionOrder.Add("context"), priority: 10);
// Act
evt.Trigger(1, EventPropagation.All);
// Assert
Assert.That(executionOrder, Is.EqualTo(new[] { "context", "normal" }));
}
[Test]
public void UntilHandled_With_Mixed_Handlers_Should_Respect_Priority()
{
// Arrange
var evt = new PriorityEvent<int>();
var executionOrder = new List<string>();
evt.Register(x => executionOrder.Add("normal-low"), priority: 1);
evt.RegisterWithContext(ctx =>
{
executionOrder.Add("context-high");
ctx.MarkAsHandled();
}, priority: 10);
evt.Register(x => executionOrder.Add("normal-mid"), priority: 5);
// Act
evt.Trigger(1, EventPropagation.UntilHandled);
// Assert
Assert.That(executionOrder, Is.EqualTo(new[] { "context-high" }));
}
[Test]
public void Highest_Propagation_Should_Execute_All_Highest_Priority_Handlers()
{
// Arrange
var evt = new PriorityEvent<int>();
var executionOrder = new List<string>();
evt.Register(x => executionOrder.Add("normal-high"), priority: 10);
evt.RegisterWithContext(ctx => executionOrder.Add("context-high"), priority: 10);
evt.Register(x => executionOrder.Add("normal-low"), priority: 1);
// Act
evt.Trigger(1, EventPropagation.Highest);
// Assert
Assert.That(executionOrder.Count, Is.EqualTo(2));
Assert.That(executionOrder, Does.Contain("normal-high"));
Assert.That(executionOrder, Does.Contain("context-high"));
}
}

View File

@ -30,7 +30,6 @@ public class MicrosoftDiContainerTests
}
private MicrosoftDiContainer _container = null!;
private readonly Dictionary<Type, object> _mockContextServices = new();
/// <summary>
/// 测试注册单例实例的功能
@ -249,12 +248,18 @@ public class MicrosoftDiContainerTests
[Test]
public void Contains_WithExistingInstance_Should_ReturnTrue()
{
// 使用 RegisterSingleton 方法来避免与其他测试方法重复
var instance = new TestService();
_container.Register(instance);
_container.RegisterSingleton(instance);
// 验证容器包含该实例
Assert.That(_container.Contains<TestService>(), Is.True);
// 验证实例确实是单例
Assert.That(_container.Get<TestService>(), Is.SameAs(instance));
}
/// <summary>
/// 测试当不存在实例时检查包含关系应返回 false 的功能
/// </summary>
@ -327,6 +332,107 @@ public class MicrosoftDiContainerTests
Assert.That(_container.Contains<TestSystem>(), Is.True);
}
/// <summary>
/// 测试在容器未冻结时调用 CreateScope 应抛出异常
/// </summary>
[Test]
public void CreateScope_Should_Throw_When_Not_Frozen()
{
// Arrange
var container = new MicrosoftDiContainer();
// Act & Assert
Assert.Throws<InvalidOperationException>(() => container.CreateScope());
}
/// <summary>
/// 测试 CreateScope 在多线程环境下的线程安全性
/// </summary>
[Test]
public void CreateScope_Should_Be_Thread_Safe()
{
// Arrange
var container = new MicrosoftDiContainer();
container.RegisterSingleton<IService>(new TestService());
container.Freeze();
// Act
var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
{
using var scope = container.CreateScope();
Assert.That(scope, Is.Not.Null);
})).ToArray();
// Assert
Assert.DoesNotThrow(() => Task.WaitAll(tasks));
}
/// <summary>
/// 测试 Get 方法在多线程环境下的线程安全性
/// </summary>
[Test]
public void Get_Should_Be_Thread_Safe()
{
// Arrange
var container = new MicrosoftDiContainer();
container.RegisterSingleton<IService>(new TestService());
container.Freeze();
// Act
var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
{
var service = container.Get<IService>();
Assert.That(service, Is.Not.Null);
})).ToArray();
// Assert
Assert.DoesNotThrow(() => Task.WaitAll(tasks));
}
/// <summary>
/// 测试 GetAll 方法在多线程环境下的线程安全性
/// </summary>
[Test]
public void GetAll_Should_Be_Thread_Safe()
{
// Arrange
var container = new MicrosoftDiContainer();
container.RegisterSingleton<IService>(new TestService());
container.Freeze();
// Act
var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
{
var services = container.GetAll<IService>();
Assert.That(services, Is.Not.Null);
})).ToArray();
// Assert
Assert.DoesNotThrow(() => Task.WaitAll(tasks));
}
/// <summary>
/// 测试 Contains 方法在多线程环境下的线程安全性
/// </summary>
[Test]
public void Contains_Should_Be_Thread_Safe()
{
// Arrange
var container = new MicrosoftDiContainer();
container.RegisterSingleton<IService>(new TestService());
container.Freeze();
// Act
var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
{
var contains = container.Contains<IService>();
Assert.That(contains, Is.True);
})).ToArray();
// Assert
Assert.DoesNotThrow(() => Task.WaitAll(tasks));
}
}
/// <summary>

View File

@ -78,4 +78,27 @@ public class EventBus : IEventBus
{
_mEvents.GetEvent<Event<T>>().UnRegister(onEvent);
}
/// <summary>
/// 注册上下文事件监听器,默认优先级为 0
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="onEvent">事件处理回调函数,接收 EventContext 参数</param>
/// <returns>反注册接口,用于注销事件监听</returns>
public IUnRegister RegisterWithContext<T>(Action<EventContext<T>> onEvent)
{
return _mPriorityEvents.GetOrAddEvent<PriorityEvent<T>>().RegisterWithContext(onEvent);
}
/// <summary>
/// 注册上下文事件监听器,并指定优先级
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="onEvent">事件处理回调函数,接收 EventContext 参数</param>
/// <param name="priority">优先级,数值越大优先级越高</param>
/// <returns>反注册接口,用于注销事件监听</returns>
public IUnRegister RegisterWithContext<T>(Action<EventContext<T>> onEvent, int priority)
{
return _mPriorityEvents.GetOrAddEvent<PriorityEvent<T>>().RegisterWithContext(onEvent, priority);
}
}

View File

@ -9,19 +9,9 @@ namespace GFramework.Core.events;
public class PriorityEvent<T> : IEvent
{
/// <summary>
/// 事件处理器包装类,包含处理器和优先级
/// 存储已注册的上下文事件处理器列表
/// </summary>
private class EventHandler
{
public Action<T> Handler { get; }
public int Priority { get; }
public EventHandler(Action<T> handler, int priority)
{
Handler = handler;
Priority = priority;
}
}
private readonly List<ContextEventHandler> _contextHandlers = new();
/// <summary>
/// 存储已注册的事件处理器列表
@ -80,12 +70,29 @@ public class PriorityEvent<T> : IEvent
}
/// <summary>
/// 触发所有已注册的事件处理程序默认传播模式All
/// 注册一个上下文事件监听器,并指定优先级
/// </summary>
/// <param name="t">传递给事件处理程序的参数</param>
public void Trigger(T t)
/// <param name="onEvent">要注册的事件处理方法,接收 EventContext 参数</param>
/// <param name="priority">优先级,数值越大优先级越高</param>
/// <returns>IUnRegister 对象,用于稍后注销该事件监听器</returns>
public IUnRegister RegisterWithContext(Action<EventContext<T>> onEvent, int priority = 0)
{
Trigger(t, EventPropagation.All);
var handler = new ContextEventHandler(onEvent, priority);
_contextHandlers.Add(handler);
// 按优先级降序排序(高优先级在前)
_contextHandlers.Sort((a, b) => b.Priority.CompareTo(a.Priority));
return new DefaultUnRegister(() => UnRegisterContext(onEvent));
}
/// <summary>
/// 取消指定的上下文事件监听器
/// </summary>
/// <param name="onEvent">需要被注销的事件处理方法</param>
public void UnRegisterContext(Action<EventContext<T>> onEvent)
{
_contextHandlers.RemoveAll(h => h.Handler == onEvent);
}
/// <summary>
@ -93,49 +100,116 @@ public class PriorityEvent<T> : IEvent
/// </summary>
/// <param name="t">传递给事件处理程序的参数</param>
/// <param name="propagation">事件传播模式</param>
public void Trigger(T t, EventPropagation propagation)
public void Trigger(T t, EventPropagation propagation = EventPropagation.All)
{
_handled = false;
switch (propagation)
{
case EventPropagation.All:
// 触发所有处理器
foreach (var handler in _handlers)
// 使用快照避免迭代期间修改
// 合并所有处理器并按优先级排序
var allHandlersForAll = _handlers
.Select(h => (h.Priority, Handler: (Action?)(() => h.Handler.Invoke(t)),
ContextHandler: (Action<EventContext<T>>?)null, IsContext: false))
.Concat(_contextHandlers
.Select(h => (h.Priority, Handler: (Action?)null,
ContextHandler: (Action<EventContext<T>>?)h.Handler, IsContext: true)))
.OrderByDescending(h => h.Priority)
.ToList();
var contextAll = new EventContext<T>(t);
foreach (var item in allHandlersForAll)
{
handler.Handler.Invoke(t);
if (item.IsContext)
{
item.ContextHandler?.Invoke(contextAll);
}
else
{
item.Handler?.Invoke();
}
}
break;
case EventPropagation.UntilHandled:
// 触发直到某个处理器标记为已处理
foreach (var handler in _handlers)
// 合并所有处理器并按优先级排序
var allHandlers = _handlers
.Select(h => (h.Priority, Handler: (Action?)(() => h.Handler.Invoke(t)),
ContextHandler: (Action<EventContext<T>>?)null, IsContext: false))
.Concat(_contextHandlers
.Select(h => (h.Priority, Handler: (Action?)null,
ContextHandler: (Action<EventContext<T>>?)h.Handler, IsContext: true)))
.OrderByDescending(h => h.Priority)
.ToList();
var context = new EventContext<T>(t);
foreach (var item in allHandlers)
{
handler.Handler.Invoke(t);
if (_handled) break;
if (item.IsContext)
{
item.ContextHandler?.Invoke(context);
if (context.IsHandled) break;
}
else
{
item.Handler?.Invoke();
if (_handled) break; // 保持向后兼容
}
}
break;
case EventPropagation.Highest:
// 仅触发最高优先级的处理器
if (_handlers.Count > 0)
// 使用快照避免迭代期间修改
var normalSnapshot = _handlers.ToArray();
var contextSnapshot = _contextHandlers.ToArray();
// 找到最高优先级
var highestPriority = int.MinValue;
if (normalSnapshot.Length > 0)
highestPriority = Math.Max(highestPriority, normalSnapshot[0].Priority);
if (contextSnapshot.Length > 0)
highestPriority = Math.Max(highestPriority, contextSnapshot[0].Priority);
if (highestPriority != int.MinValue)
{
var highestPriority = _handlers[0].Priority;
foreach (var handler in _handlers)
// 触发最高优先级的普通处理器
foreach (var handler in normalSnapshot)
{
if (handler.Priority < highestPriority) break;
handler.Handler.Invoke(t);
}
// 触发最高优先级的上下文处理器
var contextHighest = new EventContext<T>(t);
foreach (var handler in contextSnapshot)
{
if (handler.Priority < highestPriority) break;
handler.Handler.Invoke(contextHighest);
}
}
break;
}
}
/// <summary>
/// 标记事件为已处理(用于 UntilHandled 传播模式)
/// 事件处理器包装类,包含处理器和优先级
/// </summary>
public void MarkAsHandled()
private sealed class EventHandler(Action<T> handler, int priority)
{
_handled = true;
public Action<T> Handler { get; } = handler;
public int Priority { get; } = priority;
}
}
/// <summary>
/// 上下文事件处理器包装类,包含处理器和优先级
/// </summary>
private sealed class ContextEventHandler(Action<EventContext<T>> handler, int priority)
{
public Action<EventContext<T>> Handler { get; } = handler;
public int Priority { get; } = priority;
}
}

View File

@ -10,7 +10,7 @@ public static class SpanExtensions
/// </summary>
/// <typeparam name="T">目标类型,必须实现 ISpanParsable 接口</typeparam>
/// <param name="span">要解析的字符 span</param>
/// <param name="result">解析结果</param>
/// <param name="result">解析结果,失败时为 default(T)</param>
/// <returns>如果解析成功返回 true否则返回 false</returns>
/// <example>
/// <code>
@ -21,7 +21,7 @@ public static class SpanExtensions
/// }
/// </code>
/// </example>
public static bool TryParseValue<T>(this ReadOnlySpan<char> span, out T? result) where T : ISpanParsable<T>
public static bool TryParseValue<T>(this ReadOnlySpan<char> span, out T result) where T : ISpanParsable<T>
{
return T.TryParse(span, null, out result);
}
@ -47,6 +47,7 @@ public static class SpanExtensions
if (item.Equals(value))
count++;
}
return count;
}
}
}

View File

@ -363,25 +363,25 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// <returns>服务实例或null</returns>
public T? Get<T>() where T : class
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中查找已注册的实例
var serviceType = typeof(T);
var descriptor = GetServicesUnsafe.FirstOrDefault(s =>
s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType));
if (descriptor?.ImplementationInstance is T instance)
{
return instance;
}
// 在未冻结状态下无法调用工厂方法或创建实例返回null
return null;
}
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中查找已注册的实例
var serviceType = typeof(T);
var descriptor = GetServicesUnsafe.FirstOrDefault(s =>
s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType));
if (descriptor?.ImplementationInstance is T instance)
{
return instance;
}
// 在未冻结状态下无法调用工厂方法或创建实例返回null
return null;
}
var result = _provider!.GetService<T>();
_logger.Debug(result != null
? $"Retrieved instance: {typeof(T).Name}"
@ -402,18 +402,19 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// <returns>服务实例或null</returns>
public object? Get(Type type)
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中查找已注册的实例
var descriptor =
GetServicesUnsafe.FirstOrDefault(s => s.ServiceType == type || type.IsAssignableFrom(s.ServiceType));
return descriptor?.ImplementationInstance;
}
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中查找已注册的实例
var descriptor =
GetServicesUnsafe.FirstOrDefault(s =>
s.ServiceType == type || type.IsAssignableFrom(s.ServiceType));
return descriptor?.ImplementationInstance;
}
var result = _provider!.GetService(type);
_logger.Debug(result != null
? $"Retrieved instance: {type.Name}"
@ -491,36 +492,36 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// <returns>只读的服务实例列表</returns>
public IReadOnlyList<T> GetAll<T>() where T : class
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中获取已注册的实例
var serviceType = typeof(T);
var registeredServices = GetServicesUnsafe
.Where(s => s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType)).ToList();
var result = new List<T>();
foreach (var descriptor in registeredServices)
{
if (descriptor.ImplementationInstance is T instance)
{
result.Add(instance);
}
else if (descriptor.ImplementationFactory != null)
{
// 在未冻结状态下无法调用工厂方法,跳过
}
else if (descriptor.ImplementationType != null)
{
// 在未冻结状态下无法创建实例,跳过
}
}
return result;
}
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中获取已注册的实例
var serviceType = typeof(T);
var registeredServices = GetServicesUnsafe
.Where(s => s.ServiceType == serviceType || serviceType.IsAssignableFrom(s.ServiceType)).ToList();
var result = new List<T>();
foreach (var descriptor in registeredServices)
{
if (descriptor.ImplementationInstance is T instance)
{
result.Add(instance);
}
else if (descriptor.ImplementationFactory != null)
{
// 在未冻结状态下无法调用工厂方法,跳过
}
else if (descriptor.ImplementationType != null)
{
// 在未冻结状态下无法创建实例,跳过
}
}
return result;
}
var services = _provider!.GetServices<T>().ToList();
_logger.Debug($"Retrieved {services.Count} instances of {typeof(T).Name}");
return services;
@ -539,36 +540,36 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// <exception cref="InvalidOperationException">当容器未冻结时抛出</exception>
public IReadOnlyList<object> GetAll(Type type)
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中获取已注册的实例
var registeredServices = GetServicesUnsafe
.Where(s => s.ServiceType == type || type.IsAssignableFrom(s.ServiceType))
.ToList();
var result = new List<object>();
foreach (var descriptor in registeredServices)
{
if (descriptor.ImplementationInstance != null)
{
result.Add(descriptor.ImplementationInstance);
}
else if (descriptor.ImplementationFactory != null)
{
// 在未冻结状态下无法调用工厂方法,跳过
}
else if (descriptor.ImplementationType != null)
{
// 在未冻结状态下无法创建实例,跳过
}
}
return result;
}
_lock.EnterReadLock();
try
{
if (_provider == null)
{
// 如果容器未冻结,从服务集合中获取已注册的实例
var registeredServices = GetServicesUnsafe
.Where(s => s.ServiceType == type || type.IsAssignableFrom(s.ServiceType))
.ToList();
var result = new List<object>();
foreach (var descriptor in registeredServices)
{
if (descriptor.ImplementationInstance != null)
{
result.Add(descriptor.ImplementationInstance);
}
else if (descriptor.ImplementationFactory != null)
{
// 在未冻结状态下无法调用工厂方法,跳过
}
else if (descriptor.ImplementationType != null)
{
// 在未冻结状态下无法创建实例,跳过
}
}
return result;
}
var services = _provider!.GetServices(type).ToList();
_logger.Debug($"Retrieved {services.Count} instances of {type.Name}");
return services.Where(o => o != null).Cast<object>().ToList();
@ -605,12 +606,12 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// <returns>true表示包含该类型实例false表示不包含</returns>
public bool Contains<T>() where T : class
{
if (_provider == null)
return GetServicesUnsafe.Any(s => s.ServiceType == typeof(T));
_lock.EnterReadLock();
try
{
if (_provider == null)
return GetServicesUnsafe.Any(s => s.ServiceType == typeof(T));
return _provider.GetService<T>() != null;
}
finally
@ -706,16 +707,17 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// <exception cref="InvalidOperationException">当容器未冻结时抛出</exception>
public IServiceScope CreateScope()
{
if (_provider == null)
{
const string errorMsg = "Cannot create scope before container is frozen";
_logger.Error(errorMsg);
throw new InvalidOperationException(errorMsg);
}
_lock.EnterReadLock();
try
{
// 在锁内检查,避免竞态条件
if (!_frozen || _provider == null)
{
const string errorMsg = "Cannot create scope before container is frozen";
_logger.Error(errorMsg);
throw new InvalidOperationException(errorMsg);
}
var scope = _provider.CreateScope();
_logger.Debug("Service scope created");
return scope;