diff --git a/GFramework.Core.Abstractions/events/EventContext.cs b/GFramework.Core.Abstractions/events/EventContext.cs
new file mode 100644
index 0000000..6d4e736
--- /dev/null
+++ b/GFramework.Core.Abstractions/events/EventContext.cs
@@ -0,0 +1,26 @@
+namespace GFramework.Core.Abstractions.events;
+
+///
+/// 事件上下文,包装事件数据并提供控制方法
+///
+/// 事件数据类型
+public class EventContext(T data)
+{
+ ///
+ /// 事件数据
+ ///
+ public T Data { get; } = data;
+
+ ///
+ /// 事件是否已被处理
+ ///
+ public bool IsHandled { get; private set; }
+
+ ///
+ /// 标记事件为已处理,停止后续传播(仅对 UntilHandled 模式有效)
+ ///
+ public void MarkAsHandled()
+ {
+ IsHandled = true;
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/events/EventBusPriorityTests.cs b/GFramework.Core.Tests/events/EventBusPriorityTests.cs
index 9a8a832..2f6d013 100644
--- a/GFramework.Core.Tests/events/EventBusPriorityTests.cs
+++ b/GFramework.Core.Tests/events/EventBusPriorityTests.cs
@@ -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();
+
+ eventBus.RegisterWithContext(ctx =>
+ {
+ executionOrder.Add(1);
+ ctx.MarkAsHandled();
+ }, priority: 10);
+
+ eventBus.RegisterWithContext(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();
+
+ eventBus.RegisterWithContext(ctx => executionOrder.Add(1), priority: 10);
+ eventBus.RegisterWithContext(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(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();
+
+ eventBus.RegisterWithContext(ctx => executionOrder.Add(1), priority: 1);
+ eventBus.RegisterWithContext(ctx =>
+ {
+ executionOrder.Add(3);
+ ctx.MarkAsHandled();
+ }, priority: 3);
+ eventBus.RegisterWithContext(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(_ =>
+ {
+ 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(_ => Interlocked.Increment(ref counter), priority: 1);
+
+ // Act
+ var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
+ {
+ eventBus.Send(new TestEvent(), EventPropagation.All);
+ eventBus.Register(_ => { }, priority: 1);
+ })).ToArray();
+
+ // Assert
+ Assert.DoesNotThrow(() => Task.WaitAll(tasks));
+ Assert.That(counter, Is.GreaterThan(0));
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/events/PriorityEventTests.cs b/GFramework.Core.Tests/events/PriorityEventTests.cs
new file mode 100644
index 0000000..dfd3f97
--- /dev/null
+++ b/GFramework.Core.Tests/events/PriorityEventTests.cs
@@ -0,0 +1,165 @@
+using GFramework.Core.Abstractions.events;
+using GFramework.Core.events;
+using NUnit.Framework;
+
+namespace GFramework.Core.Tests.events;
+
+///
+/// 测试 PriorityEvent 的线程安全性和边界情况
+///
+[TestFixture]
+public class PriorityEventTests
+{
+ [Test]
+ public void Trigger_Should_Not_Throw_When_Handler_Unregisters_Itself()
+ {
+ // Arrange
+ var evt = new PriorityEvent();
+ 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();
+ 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();
+ var unregisters = new List();
+
+ 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? 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();
+ var executionOrder = new List();
+
+ 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();
+ var executionOrder = new List();
+
+ 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();
+ var executionOrder = new List();
+
+ 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();
+ var executionOrder = new List();
+
+ 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"));
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/ioc/MicrosoftDiContainerTests.cs b/GFramework.Core.Tests/ioc/MicrosoftDiContainerTests.cs
index 6c9c10a..fba566f 100644
--- a/GFramework.Core.Tests/ioc/MicrosoftDiContainerTests.cs
+++ b/GFramework.Core.Tests/ioc/MicrosoftDiContainerTests.cs
@@ -30,7 +30,6 @@ public class MicrosoftDiContainerTests
}
private MicrosoftDiContainer _container = null!;
- private readonly Dictionary _mockContextServices = new();
///
/// 测试注册单例实例的功能
@@ -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(), Is.True);
+ // 验证实例确实是单例
+ Assert.That(_container.Get(), Is.SameAs(instance));
}
+
///
/// 测试当不存在实例时检查包含关系应返回 false 的功能
///
@@ -327,6 +332,107 @@ public class MicrosoftDiContainerTests
Assert.That(_container.Contains(), Is.True);
}
+
+ ///
+ /// 测试在容器未冻结时调用 CreateScope 应抛出异常
+ ///
+ [Test]
+ public void CreateScope_Should_Throw_When_Not_Frozen()
+ {
+ // Arrange
+ var container = new MicrosoftDiContainer();
+
+ // Act & Assert
+ Assert.Throws(() => container.CreateScope());
+ }
+
+ ///
+ /// 测试 CreateScope 在多线程环境下的线程安全性
+ ///
+ [Test]
+ public void CreateScope_Should_Be_Thread_Safe()
+ {
+ // Arrange
+ var container = new MicrosoftDiContainer();
+ container.RegisterSingleton(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));
+ }
+
+ ///
+ /// 测试 Get 方法在多线程环境下的线程安全性
+ ///
+ [Test]
+ public void Get_Should_Be_Thread_Safe()
+ {
+ // Arrange
+ var container = new MicrosoftDiContainer();
+ container.RegisterSingleton(new TestService());
+ container.Freeze();
+
+ // Act
+ var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
+ {
+ var service = container.Get();
+ Assert.That(service, Is.Not.Null);
+ })).ToArray();
+
+ // Assert
+ Assert.DoesNotThrow(() => Task.WaitAll(tasks));
+ }
+
+ ///
+ /// 测试 GetAll 方法在多线程环境下的线程安全性
+ ///
+ [Test]
+ public void GetAll_Should_Be_Thread_Safe()
+ {
+ // Arrange
+ var container = new MicrosoftDiContainer();
+ container.RegisterSingleton(new TestService());
+ container.Freeze();
+
+ // Act
+ var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
+ {
+ var services = container.GetAll();
+ Assert.That(services, Is.Not.Null);
+ })).ToArray();
+
+ // Assert
+ Assert.DoesNotThrow(() => Task.WaitAll(tasks));
+ }
+
+ ///
+ /// 测试 Contains 方法在多线程环境下的线程安全性
+ ///
+ [Test]
+ public void Contains_Should_Be_Thread_Safe()
+ {
+ // Arrange
+ var container = new MicrosoftDiContainer();
+ container.RegisterSingleton(new TestService());
+ container.Freeze();
+
+ // Act
+ var tasks = Enumerable.Range(0, 100).Select(_ => Task.Run(() =>
+ {
+ var contains = container.Contains();
+ Assert.That(contains, Is.True);
+ })).ToArray();
+
+ // Assert
+ Assert.DoesNotThrow(() => Task.WaitAll(tasks));
+ }
}
///
diff --git a/GFramework.Core/events/EventBus.cs b/GFramework.Core/events/EventBus.cs
index 6e142ae..a67f2b6 100644
--- a/GFramework.Core/events/EventBus.cs
+++ b/GFramework.Core/events/EventBus.cs
@@ -78,4 +78,27 @@ public class EventBus : IEventBus
{
_mEvents.GetEvent>().UnRegister(onEvent);
}
+
+ ///
+ /// 注册上下文事件监听器,默认优先级为 0
+ ///
+ /// 事件类型
+ /// 事件处理回调函数,接收 EventContext 参数
+ /// 反注册接口,用于注销事件监听
+ public IUnRegister RegisterWithContext(Action> onEvent)
+ {
+ return _mPriorityEvents.GetOrAddEvent>().RegisterWithContext(onEvent);
+ }
+
+ ///
+ /// 注册上下文事件监听器,并指定优先级
+ ///
+ /// 事件类型
+ /// 事件处理回调函数,接收 EventContext 参数
+ /// 优先级,数值越大优先级越高
+ /// 反注册接口,用于注销事件监听
+ public IUnRegister RegisterWithContext(Action> onEvent, int priority)
+ {
+ return _mPriorityEvents.GetOrAddEvent>().RegisterWithContext(onEvent, priority);
+ }
}
\ No newline at end of file
diff --git a/GFramework.Core/events/PriorityEvent.cs b/GFramework.Core/events/PriorityEvent.cs
index 3b07503..c88a235 100644
--- a/GFramework.Core/events/PriorityEvent.cs
+++ b/GFramework.Core/events/PriorityEvent.cs
@@ -9,19 +9,9 @@ namespace GFramework.Core.events;
public class PriorityEvent : IEvent
{
///
- /// 事件处理器包装类,包含处理器和优先级
+ /// 存储已注册的上下文事件处理器列表
///
- private class EventHandler
- {
- public Action Handler { get; }
- public int Priority { get; }
-
- public EventHandler(Action handler, int priority)
- {
- Handler = handler;
- Priority = priority;
- }
- }
+ private readonly List _contextHandlers = new();
///
/// 存储已注册的事件处理器列表
@@ -80,12 +70,29 @@ public class PriorityEvent : IEvent
}
///
- /// 触发所有已注册的事件处理程序(默认传播模式:All)
+ /// 注册一个上下文事件监听器,并指定优先级
///
- /// 传递给事件处理程序的参数
- public void Trigger(T t)
+ /// 要注册的事件处理方法,接收 EventContext 参数
+ /// 优先级,数值越大优先级越高
+ /// IUnRegister 对象,用于稍后注销该事件监听器
+ public IUnRegister RegisterWithContext(Action> 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));
+ }
+
+ ///
+ /// 取消指定的上下文事件监听器
+ ///
+ /// 需要被注销的事件处理方法
+ public void UnRegisterContext(Action> onEvent)
+ {
+ _contextHandlers.RemoveAll(h => h.Handler == onEvent);
}
///
@@ -93,49 +100,116 @@ public class PriorityEvent : IEvent
///
/// 传递给事件处理程序的参数
/// 事件传播模式
- 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>?)null, IsContext: false))
+ .Concat(_contextHandlers
+ .Select(h => (h.Priority, Handler: (Action?)null,
+ ContextHandler: (Action>?)h.Handler, IsContext: true)))
+ .OrderByDescending(h => h.Priority)
+ .ToList();
+
+ var contextAll = new EventContext(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>?)null, IsContext: false))
+ .Concat(_contextHandlers
+ .Select(h => (h.Priority, Handler: (Action?)null,
+ ContextHandler: (Action>?)h.Handler, IsContext: true)))
+ .OrderByDescending(h => h.Priority)
+ .ToList();
+
+ var context = new EventContext(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);
+ foreach (var handler in contextSnapshot)
+ {
+ if (handler.Priority < highestPriority) break;
+ handler.Handler.Invoke(contextHighest);
+ }
}
+
break;
}
}
///
- /// 标记事件为已处理(用于 UntilHandled 传播模式)
+ /// 事件处理器包装类,包含处理器和优先级
///
- public void MarkAsHandled()
+ private sealed class EventHandler(Action handler, int priority)
{
- _handled = true;
+ public Action Handler { get; } = handler;
+ public int Priority { get; } = priority;
}
-}
+
+ ///
+ /// 上下文事件处理器包装类,包含处理器和优先级
+ ///
+ private sealed class ContextEventHandler(Action> handler, int priority)
+ {
+ public Action> Handler { get; } = handler;
+ public int Priority { get; } = priority;
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core/extensions/SpanExtensions.cs b/GFramework.Core/extensions/SpanExtensions.cs
index c5890b7..d24145f 100644
--- a/GFramework.Core/extensions/SpanExtensions.cs
+++ b/GFramework.Core/extensions/SpanExtensions.cs
@@ -10,7 +10,7 @@ public static class SpanExtensions
///
/// 目标类型,必须实现 ISpanParsable 接口
/// 要解析的字符 span
- /// 解析结果
+ /// 解析结果,失败时为 default(T)
/// 如果解析成功返回 true,否则返回 false
///
///
@@ -21,7 +21,7 @@ public static class SpanExtensions
/// }
///
///
- public static bool TryParseValue(this ReadOnlySpan span, out T? result) where T : ISpanParsable
+ public static bool TryParseValue(this ReadOnlySpan span, out T result) where T : ISpanParsable
{
return T.TryParse(span, null, out result);
}
@@ -47,6 +47,7 @@ public static class SpanExtensions
if (item.Equals(value))
count++;
}
+
return count;
}
-}
+}
\ No newline at end of file
diff --git a/GFramework.Core/ioc/MicrosoftDiContainer.cs b/GFramework.Core/ioc/MicrosoftDiContainer.cs
index f7eda5a..68b1a86 100644
--- a/GFramework.Core/ioc/MicrosoftDiContainer.cs
+++ b/GFramework.Core/ioc/MicrosoftDiContainer.cs
@@ -363,25 +363,25 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// 服务实例或null
public T? Get() 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();
_logger.Debug(result != null
? $"Retrieved instance: {typeof(T).Name}"
@@ -402,18 +402,19 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// 服务实例或null
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)
/// 只读的服务实例列表
public IReadOnlyList GetAll() 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();
- 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();
+ 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().ToList();
_logger.Debug($"Retrieved {services.Count} instances of {typeof(T).Name}");
return services;
@@ -539,36 +540,36 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null)
/// 当容器未冻结时抛出
public IReadOnlyList