diff --git a/Dalamud/IoC/Internal/ServiceScope.cs b/Dalamud/IoC/Internal/ServiceScope.cs index c21e73f34..c243eca28 100644 --- a/Dalamud/IoC/Internal/ServiceScope.cs +++ b/Dalamud/IoC/Internal/ServiceScope.cs @@ -1,7 +1,10 @@ -using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Serilog; + namespace Dalamud.IoC.Internal; /// @@ -41,8 +44,8 @@ internal class ServiceScopeImpl : IServiceScope { private readonly ServiceContainer container; - private readonly List privateScopedObjects = new(); - private readonly List scopeCreatedObjects = new(); + private readonly List privateScopedObjects = []; + private readonly ConcurrentDictionary> scopeCreatedObjects = new(); /// /// Initializes a new instance of the class. @@ -77,34 +80,39 @@ internal class ServiceScopeImpl : IServiceScope /// The type of object to create. /// Additional scoped objects. /// The created object, or null. - public async Task CreatePrivateScopedObject(Type objectType, params object[] scopedObjects) - { - var instance = this.scopeCreatedObjects.FirstOrDefault(x => x.GetType() == objectType); - if (instance != null) - return instance; - - instance = - await this.container.CreateAsync(objectType, scopedObjects.Concat(this.privateScopedObjects).ToArray()); - if (instance != null) - this.scopeCreatedObjects.Add(instance); - - return instance; - } + public Task CreatePrivateScopedObject(Type objectType, params object[] scopedObjects) => + this.scopeCreatedObjects.GetOrAdd( + objectType, + static (objectType, p) => p.Scope.container.CreateAsync( + objectType, + p.Objects.Concat(p.Scope.privateScopedObjects).ToArray()), + (Scope: this, Objects: scopedObjects)); /// public void Dispose() { - foreach (var createdObject in this.scopeCreatedObjects) + foreach (var objectTask in this.scopeCreatedObjects) { - switch (createdObject) - { - case IInternalDisposableService d: - d.DisposeService(); - break; - case IDisposable d: - d.Dispose(); - break; - } + objectTask.Value.ContinueWith( + static r => + { + if (!r.IsCompletedSuccessfully) + { + if (r.Exception is { } e) + Log.Error(e, "{what}: Failed to load.", nameof(ServiceScopeImpl)); + return; + } + + switch (r.Result) + { + case IInternalDisposableService d: + d.DisposeService(); + break; + case IDisposable d: + d.Dispose(); + break; + } + }); } } }