From fbcd9b55b2f0c8f5f2cba1f54a736e036ba20526 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Sun, 7 May 2023 11:30:31 +0900 Subject: [PATCH] Support LifetimeScope.Enqueue* multiply --- .../Runtime/Unity/ExtraInstaller.cs | 23 ----- .../Runtime/Unity/ExtraInstaller.cs.meta | 11 --- .../VContainer/Runtime/Unity/LifetimeScope.cs | 84 ++++++++++--------- .../Tests/Unity/LifetimeScopeTest.cs | 82 ++++++++++++++---- .../ProjectSettings/EditorSettings.asset | 4 + 5 files changed, 114 insertions(+), 90 deletions(-) delete mode 100644 VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs delete mode 100644 VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs.meta diff --git a/VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs b/VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs deleted file mode 100644 index 8065cd67..00000000 --- a/VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections; -using System.Collections.Generic; - -namespace VContainer.Unity -{ - public sealed class ExtraInstaller : IInstaller, IEnumerable - { - readonly IList extraInstallers = new List(); - - public IEnumerator GetEnumerator() => extraInstallers.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public void Add(IInstaller installer) => extraInstallers.Add(installer); - - public void Install(IContainerBuilder builder) - { - foreach (var installer in extraInstallers) - { - installer.Install(builder); - } - } - } -} \ No newline at end of file diff --git a/VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs.meta b/VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs.meta deleted file mode 100644 index 4c06b567..00000000 --- a/VContainer/Assets/VContainer/Runtime/Unity/ExtraInstaller.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 39c35ddf379c439088aff70a3646ce02 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs b/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs index 81f4f393..2d3d12aa 100644 --- a/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs +++ b/VContainer/Assets/VContainer/Runtime/Unity/LifetimeScope.cs @@ -11,26 +11,40 @@ public partial class LifetimeScope : MonoBehaviour, IDisposable { public readonly struct ParentOverrideScope : IDisposable { - readonly LifetimeScope parent; - public ParentOverrideScope(LifetimeScope nextParent) { - parent = nextParent; - overrideParent = nextParent; + lock (SyncRoot) + { + GlobalOverrideParents.Push(nextParent); + } } - + public void Dispose() { - //don't remove in case it was overwritten - if(overrideParent == parent) - overrideParent = null; + lock (SyncRoot) + { + GlobalOverrideParents.Pop(); + } } } public readonly struct ExtraInstallationScope : IDisposable { - public ExtraInstallationScope(IInstaller installer) => EnqueueExtra(installer); - void IDisposable.Dispose() => RemoveExtra(); + public ExtraInstallationScope(IInstaller installer) + { + lock (SyncRoot) + { + GlobalExtraInstallers.Push(installer); + } + } + + void IDisposable.Dispose() + { + lock (SyncRoot) + { + GlobalExtraInstallers.Pop(); + } + } } [SerializeField] @@ -42,8 +56,8 @@ public void Dispose() [SerializeField] protected List autoInjectGameObjects; - static LifetimeScope overrideParent; - static ExtraInstaller extraInstaller; + static readonly Stack GlobalOverrideParents = new Stack(); + static readonly Stack GlobalExtraInstallers = new Stack(); static readonly object SyncRoot = new object(); static LifetimeScope Create(IInstaller installer = null) @@ -53,7 +67,7 @@ static LifetimeScope Create(IInstaller installer = null) var newScope = gameObject.AddComponent(); if (installer != null) { - newScope.extraInstallers.Add(installer); + newScope.localExtraInstallers.Add(installer); } gameObject.SetActive(true); return newScope; @@ -101,27 +115,11 @@ static LifetimeScope Find(Type type) return (LifetimeScope)FindObjectOfType(type); } - static void EnqueueExtra(IInstaller installer) - { - lock (SyncRoot) - { - if (extraInstaller != null) - extraInstaller.Add(installer); - else - extraInstaller = new ExtraInstaller { installer }; - } - } - - static void RemoveExtra() - { - lock (SyncRoot) extraInstaller = null; - } - public IObjectResolver Container { get; private set; } public LifetimeScope Parent { get; private set; } public bool IsRoot { get; set; } - readonly List extraInstallers = new List(); + readonly List localExtraInstallers = new List(); protected virtual void Awake() { @@ -198,8 +196,6 @@ public void Build() Container = builder.Build(); } - extraInstallers.Clear(); - AutoInjectAll(); AwakeWaitingChildren(this); } @@ -220,7 +216,7 @@ public TScope CreateChild(IInstaller installer = null) var child = childGameObject.AddComponent(); if (installer != null) { - child.extraInstallers.Add(installer); + child.localExtraInstallers.Add(installer); } child.parentReference.Object = this; childGameObject.SetActive(true); @@ -248,7 +244,7 @@ public TScope CreateChildFromPrefab(TScope prefab, IInstaller installer var child = Instantiate(prefab, transform, false); if (installer != null) { - child.extraInstallers.Add(installer); + child.localExtraInstallers.Add(installer); } child.parentReference.Object = this; if (wasActive) @@ -267,17 +263,19 @@ void InstallTo(IContainerBuilder builder) { Configure(builder); - foreach (var installer in extraInstallers) + foreach (var installer in localExtraInstallers) { installer.Install(builder); } + localExtraInstallers.Clear(); - ExtraInstaller extraInstallerStatic; lock (SyncRoot) { - extraInstallerStatic = LifetimeScope.extraInstaller; + foreach (var installer in GlobalExtraInstallers) + { + installer.Install(builder); + } } - extraInstallerStatic?.Install(builder); builder.RegisterInstance(this).AsSelf(); EntryPointsBuilder.EnsureDispatcherRegistered(builder); @@ -303,9 +301,13 @@ LifetimeScope GetRuntimeParent() $"{name} could not found parent reference of type : {parentReference.Type}"); } - var nextParent = overrideParent; - if (nextParent != null) - return nextParent; + lock (SyncRoot) + { + if (GlobalOverrideParents.Count > 0) + { + return GlobalOverrideParents.Peek(); + } + } // Find root from settings if (VContainerSettings.Instance != null) diff --git a/VContainer/Assets/VContainer/Tests/Unity/LifetimeScopeTest.cs b/VContainer/Assets/VContainer/Tests/Unity/LifetimeScopeTest.cs index 52c6b1bc..23fd230f 100644 --- a/VContainer/Assets/VContainer/Tests/Unity/LifetimeScopeTest.cs +++ b/VContainer/Assets/VContainer/Tests/Unity/LifetimeScopeTest.cs @@ -8,21 +8,6 @@ namespace VContainer.Tests.Unity { public class LifetimeScopeTest { - [Test] - public void EnqueueParent() - { - var parent = new GameObject("LifetimeScope").AddComponent(); - - using (LifetimeScope.EnqueueParent(parent)) - { - var child = new GameObject("LifetimeScope Child 1").AddComponent(); - Assert.That(child.Parent, Is.EqualTo(parent)); - } - - var child2 = new GameObject("LifetimeScope Child 2").AddComponent(); - Assert.That(child2.Parent, Is.Null); - } - [UnityTest] public IEnumerator Create() { @@ -159,6 +144,73 @@ public void CreateScopeWithSingleton() Assert.That(childEntryPoint, Is.EqualTo(parentEntryPoint)); } + [Test] + public void EnqueueParent() + { + var parent = new GameObject("LifetimeScope").AddComponent(); + + using (LifetimeScope.EnqueueParent(parent)) + { + var child = new GameObject("LifetimeScope Child 1").AddComponent(); + Assert.That(child.Parent, Is.EqualTo(parent)); + } + + var child2 = new GameObject("LifetimeScope Child 2").AddComponent(); + Assert.That(child2.Parent, Is.Null); + } + + [Test] + public void EnqueueParent_Multiply() + { + var parent1 = new GameObject("LifetimeScope Parent 1").AddComponent(); + + using (LifetimeScope.EnqueueParent(parent1)) + { + var parent2 = new GameObject("LifetimeScope Parent 2").AddComponent(); + Assert.That(parent2.Parent, Is.EqualTo(parent1)); + + using (LifetimeScope.EnqueueParent(parent2)) + { + var child = new GameObject("LifetimeScope Child").AddComponent(); + Assert.That(child.Parent, Is.EqualTo(parent2)); + } + } + } + + [Test] + public void EnqueueExtraInstaller() + { + using (LifetimeScope.Enqueue(builder => builder.Register(Lifetime.Scoped))) + { + var scope1 = new GameObject("LifetimeScope 1").AddComponent(); + Assert.That(scope1.Container.Resolve(), Is.InstanceOf()); + + using (LifetimeScope.Enqueue(builder => builder.Register(Lifetime.Scoped))) + { + var scope2 = new GameObject("LifetimeScope 2").AddComponent(); + Assert.That(scope2.Container.Resolve(), Is.InstanceOf()); + Assert.That(scope2.Container.Resolve(), Is.InstanceOf()); + } + + var scope3 = new GameObject("LifetimeScope 3").AddComponent(); + Assert.That(scope3.Container.Resolve(), Is.InstanceOf()); + Assert.Throws(() => + { + scope3.Container.Resolve(); + }); + } + + var scope4 = new GameObject("LifetimeScope 4").AddComponent(); + Assert.Throws(() => + { + scope4.Container.Resolve(); + }); + Assert.Throws(() => + { + scope4.Container.Resolve(); + }); + } + [Test] [Ignore("Resources/ will be included in the build and we want to use a different approch")] public void ParentTypeReference() diff --git a/VContainer/ProjectSettings/EditorSettings.asset b/VContainer/ProjectSettings/EditorSettings.asset index 2264506d..bf63a979 100644 --- a/VContainer/ProjectSettings/EditorSettings.asset +++ b/VContainer/ProjectSettings/EditorSettings.asset @@ -11,6 +11,7 @@ EditorSettings: m_PrefabUIEnvironment: {fileID: 0} m_SpritePackerMode: 0 m_SpritePackerPaddingPower: 1 + m_Bc7TextureCompressor: 0 m_EtcTextureCompressorBehavior: 1 m_EtcTextureFastCompressor: 1 m_EtcTextureNormalCompressor: 2 @@ -31,6 +32,7 @@ EditorSettings: m_SerializeInlineMappingsOnOneLine: 0 m_DisableCookiesInLightmapper: 1 m_AssetPipelineMode: 1 + m_RefreshImportMode: 0 m_CacheServerMode: 0 m_CacheServerEndpoint: m_CacheServerNamespacePrefix: default @@ -38,3 +40,5 @@ EditorSettings: m_CacheServerEnableUpload: 1 m_CacheServerEnableAuth: 0 m_CacheServerEnableTls: 0 + m_CacheServerValidationMode: 2 + m_CacheServerDownloadBatchSize: 128