From 32b24b3b5a23b627bdabc2db6d6739ed5b6d8c69 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Wed, 24 Jul 2024 18:39:24 +0900 Subject: [PATCH 1/4] Fix ServiceScope.CreatePrivateScopedObject concurrency --- Dalamud/IoC/Internal/ServiceScope.cs | 60 ++++++++++++++++------------ 1 file changed, 34 insertions(+), 26 deletions(-) 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; + } + }); } } } From 4b98f4e60aa9a864886d18240aa95ad6f6617c1b Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Wed, 24 Jul 2024 18:55:27 +0900 Subject: [PATCH 2/4] Remove nullability from IServiceScope.CreateAsync --- Dalamud/IoC/Internal/ServiceContainer.cs | 14 ++++++------ Dalamud/IoC/Internal/ServiceScope.cs | 8 +++---- Dalamud/Plugin/DalamudPluginInterface.cs | 24 ++++++++++++-------- Dalamud/Plugin/IDalamudPluginInterface.cs | 11 ++++++++- Dalamud/Plugin/Internal/Types/LocalPlugin.cs | 22 ++++++------------ 5 files changed, 42 insertions(+), 37 deletions(-) diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs index 7a0b4347d..06e2ff14d 100644 --- a/Dalamud/IoC/Internal/ServiceContainer.cs +++ b/Dalamud/IoC/Internal/ServiceContainer.cs @@ -84,15 +84,15 @@ internal class ServiceContainer : IServiceProvider, IServiceType /// Scoped objects to be included in the constructor. /// The scope to be used to create scoped services. /// The created object. - public async Task CreateAsync(Type objectType, object[] scopedObjects, IServiceScope? scope = null) + public async Task CreateAsync(Type objectType, object[] scopedObjects, IServiceScope? scope = null) { var scopeImpl = scope as ServiceScopeImpl; var ctor = this.FindApplicableCtor(objectType, scopedObjects); if (ctor == null) { - Log.Error("Failed to create {TypeName}, an eligible ctor with satisfiable services could not be found", objectType.FullName!); - return null; + throw new InvalidOperationException( + $"Failed to create {objectType.FullName ?? objectType.Name}; an eligible ctor with satisfiable services could not be found"); } // validate dependency versions (if they exist) @@ -116,16 +116,16 @@ internal class ServiceContainer : IServiceProvider, IServiceType var hasNull = resolvedParams.Any(p => p == null); if (hasNull) { - Log.Error("Failed to create {TypeName}, a requested service type could not be satisfied", objectType.FullName!); - return null; + throw new InvalidOperationException( + $"Failed to create {objectType.FullName ?? objectType.Name}; a requested service type could not be satisfied"); } var instance = RuntimeHelpers.GetUninitializedObject(objectType); if (!await this.InjectProperties(instance, scopedObjects, scope)) { - Log.Error("Failed to create {TypeName}, a requested property service type could not be satisfied", objectType.FullName!); - return null; + throw new InvalidOperationException( + $"Failed to create {objectType.FullName ?? objectType.Name}; a requested property service type could not be satisfied"); } var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/Dalamud/IoC/Internal/ServiceScope.cs b/Dalamud/IoC/Internal/ServiceScope.cs index c243eca28..33a4d3f54 100644 --- a/Dalamud/IoC/Internal/ServiceScope.cs +++ b/Dalamud/IoC/Internal/ServiceScope.cs @@ -25,7 +25,7 @@ internal interface IServiceScope : IDisposable /// The type of object to create. /// Scoped objects to be included in the constructor. /// The created object. - public Task CreateAsync(Type objectType, params object[] scopedObjects); + public Task CreateAsync(Type objectType, params object[] scopedObjects); /// /// Inject interfaces into public or static properties on the provided object. @@ -45,7 +45,7 @@ internal class ServiceScopeImpl : IServiceScope private readonly ServiceContainer container; private readonly List privateScopedObjects = []; - private readonly ConcurrentDictionary> scopeCreatedObjects = new(); + private readonly ConcurrentDictionary> scopeCreatedObjects = new(); /// /// Initializes a new instance of the class. @@ -63,7 +63,7 @@ internal class ServiceScopeImpl : IServiceScope } /// - public Task CreateAsync(Type objectType, params object[] scopedObjects) + public Task CreateAsync(Type objectType, params object[] scopedObjects) { return this.container.CreateAsync(objectType, scopedObjects, this); } @@ -80,7 +80,7 @@ internal class ServiceScopeImpl : IServiceScope /// The type of object to create. /// Additional scoped objects. /// The created object, or null. - public Task CreatePrivateScopedObject(Type objectType, params object[] scopedObjects) => + public Task CreatePrivateScopedObject(Type objectType, params object[] scopedObjects) => this.scopeCreatedObjects.GetOrAdd( objectType, static (objectType, p) => p.Scope.container.CreateAsync( diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index bb92b6b0c..9fb73fbe1 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using Dalamud.Configuration; using Dalamud.Configuration.Internal; @@ -26,6 +27,8 @@ using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc.Exceptions; using Dalamud.Plugin.Ipc.Internal; +using Serilog; + namespace Dalamud.Plugin; /// @@ -458,21 +461,22 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa #region Dependency Injection - /// - /// Create a new object of the provided type using its default constructor, then inject objects and properties. - /// - /// Objects to inject additionally. - /// The type to create. - /// The created and initialized type. + /// public T? Create(params object[] scopedObjects) where T : class { - var svcContainer = Service.Get(); + var t = this.CreateAsync(scopedObjects); + t.Wait(); - return (T)this.plugin.ServiceScope!.CreateAsync( - typeof(T), - this.GetPublicIocScopes(scopedObjects)).GetAwaiter().GetResult(); + if (t.Exception is { } e) + Log.Error(e, "{who}: Failed to initialize {what}", this.plugin.Name, typeof(T).FullName ?? typeof(T).Name); + + return t.IsCompletedSuccessfully ? t.Result : null; } + /// + public async Task CreateAsync(params object[] scopedObjects) where T : class => + (T)await this.plugin.ServiceScope!.CreateAsync(typeof(T), this.GetPublicIocScopes(scopedObjects)); + /// /// Inject services into properties on the provided object instance. /// diff --git a/Dalamud/Plugin/IDalamudPluginInterface.cs b/Dalamud/Plugin/IDalamudPluginInterface.cs index 6393dc5ab..b5257c033 100644 --- a/Dalamud/Plugin/IDalamudPluginInterface.cs +++ b/Dalamud/Plugin/IDalamudPluginInterface.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Threading.Tasks; using Dalamud.Configuration; using Dalamud.Game.Text; @@ -304,9 +305,17 @@ public interface IDalamudPluginInterface /// /// Objects to inject additionally. /// The type to create. - /// The created and initialized type. + /// The created and initialized type, or null on failure. T? Create(params object[] scopedObjects) where T : class; + /// + /// Create a new object of the provided type using its default constructor, then inject objects and properties. + /// + /// Objects to inject additionally. + /// The type to create. + /// A task representing the created and initialized type. + Task CreateAsync(params object[] scopedObjects) where T : class; + /// /// Inject services into properties on the provided object instance. /// diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index f7bb3495c..00fa9d243 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -417,24 +417,16 @@ internal class LocalPlugin : IDisposable try { - if (this.manifest.LoadSync && this.manifest.LoadRequiredState is 0 or 1) - { - var newInstance = await framework.RunOnFrameworkThread( - () => this.ServiceScope.CreateAsync( - this.pluginType!, - this.DalamudInterface!)).ConfigureAwait(false); - - this.instance = newInstance as IDalamudPlugin; - } - else - { - this.instance = - await this.ServiceScope.CreateAsync(this.pluginType!, this.DalamudInterface!) as IDalamudPlugin; - } + var forceFrameworkThread = this.manifest.LoadSync && this.manifest.LoadRequiredState is 0 or 1; + var newInstanceTask = forceFrameworkThread ? framework.RunOnFrameworkThread(Create) : Create(); + this.instance = await newInstanceTask.ConfigureAwait(false); + + async Task Create() => + (IDalamudPlugin)await this.ServiceScope!.CreateAsync(this.pluginType!, this.DalamudInterface!); } catch (Exception ex) { - Log.Error(ex, "Exception in plugin constructor"); + Log.Error(ex, "Exception during plugin initialization"); this.instance = null; } From db3e9a4171bc353f8e86987b29cc272a0fb68de4 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Wed, 24 Jul 2024 19:17:31 +0900 Subject: [PATCH 3/4] Add IDalamudPluginInterface.InjectAsync --- Dalamud/IoC/Internal/ServiceContainer.cs | 134 +++++++++------------- Dalamud/IoC/Internal/ServiceScope.cs | 10 +- Dalamud/Plugin/DalamudPluginInterface.cs | 37 ++++-- Dalamud/Plugin/IDalamudPluginInterface.cs | 8 ++ 4 files changed, 92 insertions(+), 97 deletions(-) diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs index 06e2ff14d..39c2007f3 100644 --- a/Dalamud/IoC/Internal/ServiceContainer.cs +++ b/Dalamud/IoC/Internal/ServiceContainer.cs @@ -86,70 +86,55 @@ internal class ServiceContainer : IServiceProvider, IServiceType /// The created object. public async Task CreateAsync(Type objectType, object[] scopedObjects, IServiceScope? scope = null) { - var scopeImpl = scope as ServiceScopeImpl; + var errorStep = "constructor lookup"; - var ctor = this.FindApplicableCtor(objectType, scopedObjects); - if (ctor == null) + try { - throw new InvalidOperationException( - $"Failed to create {objectType.FullName ?? objectType.Name}; an eligible ctor with satisfiable services could not be found"); - } + var scopeImpl = scope as ServiceScopeImpl; - // validate dependency versions (if they exist) - var parameterTypes = ctor.GetParameters().Select(p => p.ParameterType).ToList(); + var ctor = this.FindApplicableCtor(objectType, scopedObjects) + ?? throw new InvalidOperationException("An eligible ctor with satisfiable services could not be found"); - var resolvedParams = - await Task.WhenAll( - parameterTypes - .Select(async type => + errorStep = "requested service resolution"; + var resolvedParams = + await Task.WhenAll( + ctor.GetParameters() + .Select(p => p.ParameterType) + .Select(type => this.GetService(type, scopeImpl, scopedObjects))); + + var instance = RuntimeHelpers.GetUninitializedObject(objectType); + + errorStep = "property injection"; + await this.InjectProperties(instance, scopedObjects, scope); + + errorStep = "ctor invocation"; + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var thr = new Thread( + () => + { + try { - var service = await this.GetService(type, scopeImpl, scopedObjects); + ctor.Invoke(instance, resolvedParams); + } + catch (Exception e) + { + tcs.SetException(e); + return; + } - if (service == null) - { - Log.Error("Requested ctor service type {TypeName} was not available (null)", type.FullName!); - } + tcs.SetResult(); + }); - return service; - })); + thr.Start(); + await tcs.Task.ConfigureAwait(false); + thr.Join(); - var hasNull = resolvedParams.Any(p => p == null); - if (hasNull) - { - throw new InvalidOperationException( - $"Failed to create {objectType.FullName ?? objectType.Name}; a requested service type could not be satisfied"); + return instance; } - - var instance = RuntimeHelpers.GetUninitializedObject(objectType); - - if (!await this.InjectProperties(instance, scopedObjects, scope)) + catch (Exception e) { - throw new InvalidOperationException( - $"Failed to create {objectType.FullName ?? objectType.Name}; a requested property service type could not be satisfied"); + throw new AggregateException($"Failed to create {objectType.FullName ?? objectType.Name} ({errorStep})", e); } - - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var thr = new Thread( - () => - { - try - { - ctor.Invoke(instance, resolvedParams); - } - catch (Exception e) - { - tcs.SetException(e); - return; - } - - tcs.SetResult(); - }); - - thr.Start(); - await tcs.Task.ConfigureAwait(false); - thr.Join(); - - return instance; } /// @@ -159,28 +144,21 @@ internal class ServiceContainer : IServiceProvider, IServiceType /// The object instance. /// Scoped objects to be injected. /// The scope to be used to create scoped services. - /// Whether or not the injection was successful. - public async Task InjectProperties(object instance, object[] publicScopes, IServiceScope? scope = null) + /// A representing the operation. + public async ValueTask InjectProperties(object instance, object[] publicScopes, IServiceScope? scope = null) { var scopeImpl = scope as ServiceScopeImpl; var objectType = instance.GetType(); - var props = objectType.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | - BindingFlags.NonPublic).Where(x => x.GetCustomAttributes(typeof(PluginServiceAttribute)).Any()).ToArray(); + var props = + objectType + .GetProperties( + BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(x => x.GetCustomAttributes(typeof(PluginServiceAttribute)).Any()) + .ToArray(); foreach (var prop in props) - { - var service = await this.GetService(prop.PropertyType, scopeImpl, publicScopes); - if (service == null) - { - Log.Error("Requested service type {TypeName} was not available (null)", prop.PropertyType.FullName!); - return false; - } - - prop.SetValue(instance, service); - } - - return true; + prop.SetValue(instance, await this.GetService(prop.PropertyType, scopeImpl, publicScopes)); } /// @@ -192,7 +170,7 @@ internal class ServiceContainer : IServiceProvider, IServiceType /// object? IServiceProvider.GetService(Type serviceType) => this.GetSingletonService(serviceType); - private async Task GetService(Type serviceType, ServiceScopeImpl? scope, object[] scopedObjects) + private async Task GetService(Type serviceType, ServiceScopeImpl? scope, object[] scopedObjects) { if (this.interfaceToTypeMap.TryGetValue(serviceType, out var implementingType)) serviceType = implementingType; @@ -201,8 +179,8 @@ internal class ServiceContainer : IServiceProvider, IServiceType { if (scope == null) { - Log.Error("Failed to create {TypeName}, is scoped but no scope provided", serviceType.FullName!); - return null; + throw new InvalidOperationException( + $"Failed to create {serviceType.FullName ?? serviceType.Name}, is scoped but no scope provided"); } return await scope.CreatePrivateScopedObject(serviceType, scopedObjects); @@ -210,18 +188,12 @@ internal class ServiceContainer : IServiceProvider, IServiceType var singletonService = await this.GetSingletonService(serviceType, false); if (singletonService != null) - { return singletonService; - } // resolve dependency from scoped objects - var scoped = scopedObjects.FirstOrDefault(o => o.GetType().IsAssignableTo(serviceType)); - if (scoped == default) - { - return null; - } - - return scoped; + return scopedObjects.FirstOrDefault(o => o.GetType().IsAssignableTo(serviceType)) + ?? throw new InvalidOperationException( + $"Requested type {serviceType.FullName ?? serviceType.Name} could not be found from {nameof(scopedObjects)}"); } private async Task GetSingletonService(Type serviceType, bool tryGetInterface = true) diff --git a/Dalamud/IoC/Internal/ServiceScope.cs b/Dalamud/IoC/Internal/ServiceScope.cs index 33a4d3f54..fb06ec75c 100644 --- a/Dalamud/IoC/Internal/ServiceScope.cs +++ b/Dalamud/IoC/Internal/ServiceScope.cs @@ -33,8 +33,8 @@ internal interface IServiceScope : IDisposable /// /// The object instance. /// Scoped objects to be injected. - /// Whether or not the injection was successful. - public Task InjectPropertiesAsync(object instance, params object[] scopedObjects); + /// A representing the status of the operation. + public ValueTask InjectPropertiesAsync(object instance, params object[] scopedObjects); } /// @@ -69,10 +69,8 @@ internal class ServiceScopeImpl : IServiceScope } /// - public Task InjectPropertiesAsync(object instance, params object[] scopedObjects) - { - return this.container.InjectProperties(instance, scopedObjects, this); - } + public ValueTask InjectPropertiesAsync(object instance, params object[] scopedObjects) => + this.container.InjectProperties(instance, scopedObjects, this); /// /// Create a service scoped to this scope, with private scoped objects. diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 9fb73fbe1..f0882c6fe 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -468,7 +468,14 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa t.Wait(); if (t.Exception is { } e) - Log.Error(e, "{who}: Failed to initialize {what}", this.plugin.Name, typeof(T).FullName ?? typeof(T).Name); + { + Log.Error( + e, + "{who}: Exception during {where}: {what}", + this.plugin.Name, + nameof(this.Create), + typeof(T).FullName ?? typeof(T).Name); + } return t.IsCompletedSuccessfully ? t.Result : null; } @@ -477,19 +484,29 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa public async Task CreateAsync(params object[] scopedObjects) where T : class => (T)await this.plugin.ServiceScope!.CreateAsync(typeof(T), this.GetPublicIocScopes(scopedObjects)); - /// - /// Inject services into properties on the provided object instance. - /// - /// The instance to inject services into. - /// Objects to inject additionally. - /// Whether or not the injection succeeded. + /// public bool Inject(object instance, params object[] scopedObjects) { - return this.plugin.ServiceScope!.InjectPropertiesAsync( - instance, - this.GetPublicIocScopes(scopedObjects)).GetAwaiter().GetResult(); + var t = this.InjectAsync(instance, scopedObjects).AsTask(); + t.Wait(); + + if (t.Exception is { } e) + { + Log.Error( + e, + "{who}: Exception during {where}: {what}", + this.plugin.Name, + nameof(this.Inject), + instance.GetType().FullName ?? instance.GetType().Name); + } + + return t.IsCompletedSuccessfully; } + /// + public ValueTask InjectAsync(object instance, params object[] scopedObjects) => + this.plugin.ServiceScope!.InjectPropertiesAsync(instance, this.GetPublicIocScopes(scopedObjects)); + #endregion /// Unregister the plugin and dispose all references. diff --git a/Dalamud/Plugin/IDalamudPluginInterface.cs b/Dalamud/Plugin/IDalamudPluginInterface.cs index b5257c033..5205c3ed1 100644 --- a/Dalamud/Plugin/IDalamudPluginInterface.cs +++ b/Dalamud/Plugin/IDalamudPluginInterface.cs @@ -323,4 +323,12 @@ public interface IDalamudPluginInterface /// Objects to inject additionally. /// Whether or not the injection succeeded. bool Inject(object instance, params object[] scopedObjects); + + /// + /// Inject services into properties on the provided object instance. + /// + /// The instance to inject services into. + /// Objects to inject additionally. + /// A representing the status of the operation. + ValueTask InjectAsync(object instance, params object[] scopedObjects); } From a725bbf8e06c093d16aee3036551c242d48c7e11 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Wed, 24 Jul 2024 19:20:39 +0900 Subject: [PATCH 4/4] cleanup --- Dalamud/IoC/Internal/ServiceContainer.cs | 2 +- Dalamud/IoC/Internal/ServiceScope.cs | 27 ++++++++--------------- Dalamud/Plugin/DalamudPluginInterface.cs | 4 ++-- Dalamud/Plugin/IDalamudPluginInterface.cs | 4 ++-- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs index 39c2007f3..a8eacb02d 100644 --- a/Dalamud/IoC/Internal/ServiceContainer.cs +++ b/Dalamud/IoC/Internal/ServiceContainer.cs @@ -145,7 +145,7 @@ internal class ServiceContainer : IServiceProvider, IServiceType /// Scoped objects to be injected. /// The scope to be used to create scoped services. /// A representing the operation. - public async ValueTask InjectProperties(object instance, object[] publicScopes, IServiceScope? scope = null) + public async Task InjectProperties(object instance, object[] publicScopes, IServiceScope? scope = null) { var scopeImpl = scope as ServiceScopeImpl; var objectType = instance.GetType(); diff --git a/Dalamud/IoC/Internal/ServiceScope.cs b/Dalamud/IoC/Internal/ServiceScope.cs index fb06ec75c..4fc299f6e 100644 --- a/Dalamud/IoC/Internal/ServiceScope.cs +++ b/Dalamud/IoC/Internal/ServiceScope.cs @@ -17,7 +17,7 @@ internal interface IServiceScope : IDisposable /// but not directly to created objects. /// /// The scopes to add. - public void RegisterPrivateScopes(params object[] scopes); + void RegisterPrivateScopes(params object[] scopes); /// /// Create an object. @@ -25,7 +25,7 @@ internal interface IServiceScope : IDisposable /// The type of object to create. /// Scoped objects to be included in the constructor. /// The created object. - public Task CreateAsync(Type objectType, params object[] scopedObjects); + Task CreateAsync(Type objectType, params object[] scopedObjects); /// /// Inject interfaces into public or static properties on the provided object. @@ -34,7 +34,7 @@ internal interface IServiceScope : IDisposable /// The object instance. /// Scoped objects to be injected. /// A representing the status of the operation. - public ValueTask InjectPropertiesAsync(object instance, params object[] scopedObjects); + Task InjectPropertiesAsync(object instance, params object[] scopedObjects); } /// @@ -47,29 +47,20 @@ internal class ServiceScopeImpl : IServiceScope private readonly List privateScopedObjects = []; private readonly ConcurrentDictionary> scopeCreatedObjects = new(); - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. /// The container this scope will use to create services. - public ServiceScopeImpl(ServiceContainer container) - { - this.container = container; - } + public ServiceScopeImpl(ServiceContainer container) => this.container = container; /// - public void RegisterPrivateScopes(params object[] scopes) - { + public void RegisterPrivateScopes(params object[] scopes) => this.privateScopedObjects.AddRange(scopes); - } /// - public Task CreateAsync(Type objectType, params object[] scopedObjects) - { - return this.container.CreateAsync(objectType, scopedObjects, this); - } + public Task CreateAsync(Type objectType, params object[] scopedObjects) => + this.container.CreateAsync(objectType, scopedObjects, this); /// - public ValueTask InjectPropertiesAsync(object instance, params object[] scopedObjects) => + public Task InjectPropertiesAsync(object instance, params object[] scopedObjects) => this.container.InjectProperties(instance, scopedObjects, this); /// diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index f0882c6fe..ecd2e0799 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -487,7 +487,7 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa /// public bool Inject(object instance, params object[] scopedObjects) { - var t = this.InjectAsync(instance, scopedObjects).AsTask(); + var t = this.InjectAsync(instance, scopedObjects); t.Wait(); if (t.Exception is { } e) @@ -504,7 +504,7 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa } /// - public ValueTask InjectAsync(object instance, params object[] scopedObjects) => + public Task InjectAsync(object instance, params object[] scopedObjects) => this.plugin.ServiceScope!.InjectPropertiesAsync(instance, this.GetPublicIocScopes(scopedObjects)); #endregion diff --git a/Dalamud/Plugin/IDalamudPluginInterface.cs b/Dalamud/Plugin/IDalamudPluginInterface.cs index 5205c3ed1..100d4570e 100644 --- a/Dalamud/Plugin/IDalamudPluginInterface.cs +++ b/Dalamud/Plugin/IDalamudPluginInterface.cs @@ -321,7 +321,7 @@ public interface IDalamudPluginInterface /// /// The instance to inject services into. /// Objects to inject additionally. - /// Whether or not the injection succeeded. + /// Whether the injection succeeded. bool Inject(object instance, params object[] scopedObjects); /// @@ -330,5 +330,5 @@ public interface IDalamudPluginInterface /// The instance to inject services into. /// Objects to inject additionally. /// A representing the status of the operation. - ValueTask InjectAsync(object instance, params object[] scopedObjects); + Task InjectAsync(object instance, params object[] scopedObjects); }