From 11efdf642053fad2ecdb83eab1892024be427621 Mon Sep 17 00:00:00 2001 From: Alon Talmi <130899578+AlonTalmi@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:42:14 +0100 Subject: [PATCH 1/3] TryRsolve --- .../Assets/VContainer/Runtime/Container.cs | 51 +++++++++++++++++-- .../Runtime/IObjectResolverExtensions.cs | 24 +++++++++ .../Runtime/Unity/EntryPointDispatcher.cs | 9 +--- 3 files changed, 73 insertions(+), 11 deletions(-) diff --git a/VContainer/Assets/VContainer/Runtime/Container.cs b/VContainer/Assets/VContainer/Runtime/Container.cs index 639310e3..648668ce 100644 --- a/VContainer/Assets/VContainer/Runtime/Container.cs +++ b/VContainer/Assets/VContainer/Runtime/Container.cs @@ -18,6 +18,15 @@ public interface IObjectResolver : IDisposable /// This version of resolve looks for all of scopes /// object Resolve(Type type); + + /// + /// Try resolve from type + /// + /// + /// This version of resolve looks for all of scopes + /// + /// Successfully resolved + bool TryResolve(Type type, out object resolved); /// /// Resolve from meta with registration @@ -75,6 +84,18 @@ internal ScopedContainer( [MethodImpl(MethodImplOptions.AggressiveInlining)] public object Resolve(Type type) => Resolve(FindRegistration(type)); + public bool TryResolve(Type type, out object resolved) + { + if (TryFindRegistration(type, out var registration)) + { + resolved = Resolve(registration); + return true; + } + + resolved = default; + return false; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public object Resolve(Registration registration) { @@ -155,17 +176,28 @@ object CreateTrackedInstance(Registration registration) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Registration FindRegistration(Type type) + { + if (TryFindRegistration(type, out var registration)) + return registration; + + throw new VContainerException(type, $"No such registration of type: {type}"); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal bool TryFindRegistration(Type type, out Registration registration) { IScopedObjectResolver scope = this; while (scope != null) { - if (scope.TryGetRegistration(type, out var registration)) + if (scope.TryGetRegistration(type, out registration)) { - return registration; + return true; } scope = scope.Parent; } - throw new VContainerException(type, $"No such registration of type: {type}"); + + registration = default; + return false; } } @@ -203,6 +235,19 @@ public object Resolve(Type type) throw new VContainerException(type, $"No such registration of type: {type}"); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryResolve(Type type, out object resolved) + { + if (registry.TryGet(type, out var registration)) + { + resolved = Resolve(registration); + return true; + } + + resolved = default; + return false; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public object Resolve(Registration registration) { diff --git a/VContainer/Assets/VContainer/Runtime/IObjectResolverExtensions.cs b/VContainer/Assets/VContainer/Runtime/IObjectResolverExtensions.cs index cd3b15be..68967d78 100644 --- a/VContainer/Assets/VContainer/Runtime/IObjectResolverExtensions.cs +++ b/VContainer/Assets/VContainer/Runtime/IObjectResolverExtensions.cs @@ -9,6 +9,30 @@ public static class IObjectResolverExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Resolve(this IObjectResolver resolver) => (T)resolver.Resolve(typeof(T)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryResolve(this IObjectResolver resolver, out T resolved) + { + if (resolver.TryResolve(typeof(T), out var r)) + { + resolved = (T)r; + return true; + } + + resolved = default; + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ResolveOrDefault(this IObjectResolver resolver, T defaultValue = default) + { + if (resolver.TryResolve(typeof(T), out var value)) + { + return (T)value; + } + + return defaultValue; + } + // Using from CodeGen [Preserve] [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/VContainer/Assets/VContainer/Runtime/Unity/EntryPointDispatcher.cs b/VContainer/Assets/VContainer/Runtime/Unity/EntryPointDispatcher.cs index e75f6471..c47d91a4 100644 --- a/VContainer/Assets/VContainer/Runtime/Unity/EntryPointDispatcher.cs +++ b/VContainer/Assets/VContainer/Runtime/Unity/EntryPointDispatcher.cs @@ -22,14 +22,7 @@ public void Dispatch() { PlayerLoopHelper.EnsureInitialized(); - EntryPointExceptionHandler exceptionHandler = null; - try - { - exceptionHandler = container.Resolve(); - } - catch (VContainerException ex) when (ex.InvalidType == typeof(EntryPointExceptionHandler)) - { - } + EntryPointExceptionHandler exceptionHandler = container.ResolveOrDefault(); var initializables = container.Resolve>>().Value; for (var i = 0; i < initializables.Count; i++) From c0bcc1b8f56acf3c7055bf26ef71b72ab95229c9 Mon Sep 17 00:00:00 2001 From: Alon Talmi <130899578+AlonTalmi@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:42:29 +0100 Subject: [PATCH 2/3] Added Unit tests --- VContainer/Assets/Tests/ContainerTest.cs | 67 ++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/VContainer/Assets/Tests/ContainerTest.cs b/VContainer/Assets/Tests/ContainerTest.cs index ad8247d5..a9320011 100644 --- a/VContainer/Assets/Tests/ContainerTest.cs +++ b/VContainer/Assets/Tests/ContainerTest.cs @@ -328,7 +328,7 @@ public void RegisterFromFunc() Assert.That(resolved, Is.InstanceOf()); Assert.That(resolved.Service2, Is.InstanceOf()); } - + [Test] public void RegisterValueTypeFromFunc() { @@ -442,7 +442,7 @@ public void RegisterWithParameter() var resolved = container.Resolve(); Assert.That(resolved.Service2, Is.EqualTo(paramValue)); } - + { var builder = new ContainerBuilder(); builder.Register(Lifetime.Scoped); @@ -601,8 +601,10 @@ public void OnContainerDisposeCallback() builder.Register(Lifetime.Scoped); builder.Register(Lifetime.Scoped); - builder.RegisterDisposeCallback(resolver => resolvedJustBeforeDispose = resolver.Resolve()); - builder.RegisterDisposeCallback(resolver => resolvedJustBeforeDispose2 = resolver.Resolve()); + builder.RegisterDisposeCallback(resolver => + resolvedJustBeforeDispose = resolver.Resolve()); + builder.RegisterDisposeCallback(resolver => + resolvedJustBeforeDispose2 = resolver.Resolve()); var container = builder.Build(); @@ -614,5 +616,62 @@ public void OnContainerDisposeCallback() Assert.That(resolvedJustBeforeDispose, Is.Not.Null); Assert.That(resolvedJustBeforeDispose2, Is.Not.Null); } + + [Test] + public void TryResolveTransient() + { + var builder = new ContainerBuilder(); + builder.Register(Lifetime.Transient); + + var container = builder.Build(); + + Assert.That(container.TryResolve(out var obj1), Is.True); + Assert.That(container.TryResolve(out var obj2), Is.True); + Assert.That(container.TryResolve(out var obj3), Is.False); + + Assert.That(obj1, Is.TypeOf()); + Assert.That(obj2, Is.TypeOf()); + Assert.That(obj1, Is.Not.EqualTo(obj2)); + Assert.That(obj3, Is.Null); + } + + [Test] + public void TryResolveSingleton() + { + var builder = new ContainerBuilder(); + builder.Register(Lifetime.Singleton); + + var container = builder.Build(); + Assert.That(container.TryResolve(out var obj1), Is.True); + Assert.That(container.TryResolve(out var obj2), Is.True); + Assert.That(container.TryResolve(out var obj3), Is.False); + + Assert.That(obj1, Is.TypeOf()); + Assert.That(obj2, Is.TypeOf()); + Assert.That(obj1, Is.EqualTo(obj2)); + Assert.That(obj3, Is.Null); + } + + [Test] + public void TryResolveScoped() + { + var builder = new ContainerBuilder(); + builder.Register(Lifetime.Scoped); + + var container = builder.Build(); + Assert.That(container.TryResolve(out var obj1), Is.True); + Assert.That(container.TryResolve(out var obj2), Is.True); + Assert.That(container.TryResolve(out var obj3), Is.False); + + Assert.That(obj1, Is.TypeOf()); + Assert.That(obj2, Is.TypeOf()); + Assert.That(obj1, Is.EqualTo(obj2)); + Assert.That(obj3, Is.Null); + + container.Dispose(); + + Assert.That(obj1.Disposed, Is.True); +>>>>>>> 1d6258b (Added Unit tests):VContainer/Assets/VContainer/Tests/ContainerTest.cs + } } } From 921ec3dde369c7d19fc862772b7bcb57a2b64288 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 4 Apr 2024 13:38:51 +0900 Subject: [PATCH 3/3] Tweaks --- VContainer/Assets/Tests/ContainerTest.cs | 1 - .../Assets/VContainer/Runtime/Container.cs | 28 +++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/VContainer/Assets/Tests/ContainerTest.cs b/VContainer/Assets/Tests/ContainerTest.cs index a9320011..635d6618 100644 --- a/VContainer/Assets/Tests/ContainerTest.cs +++ b/VContainer/Assets/Tests/ContainerTest.cs @@ -671,7 +671,6 @@ public void TryResolveScoped() container.Dispose(); Assert.That(obj1.Disposed, Is.True); ->>>>>>> 1d6258b (Added Unit tests):VContainer/Assets/VContainer/Tests/ContainerTest.cs } } } diff --git a/VContainer/Assets/VContainer/Runtime/Container.cs b/VContainer/Assets/VContainer/Runtime/Container.cs index 648668ce..e7d0b925 100644 --- a/VContainer/Assets/VContainer/Runtime/Container.cs +++ b/VContainer/Assets/VContainer/Runtime/Container.cs @@ -18,7 +18,7 @@ public interface IObjectResolver : IDisposable /// This version of resolve looks for all of scopes /// object Resolve(Type type); - + /// /// Try resolve from type /// @@ -35,7 +35,9 @@ public interface IObjectResolver : IDisposable /// This version of resolve will look for instances from only the registration information already founds. /// object Resolve(Registration registration); + IScopedObjectResolver CreateScope(Action installation = null); + void Inject(object instance); bool TryGetRegistration(Type type, out Registration registration); } @@ -82,7 +84,14 @@ internal ScopedContainer( } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public object Resolve(Type type) => Resolve(FindRegistration(type)); + public object Resolve(Type type) + { + if (TryFindRegistration(type, out var registration)) + { + return Resolve(registration); + } + throw new VContainerException(type, $"No such registration of type: {type}"); + } public bool TryResolve(Type type, out object resolved) { @@ -174,15 +183,6 @@ object CreateTrackedInstance(Registration registration) return instance; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Registration FindRegistration(Type type) - { - if (TryFindRegistration(type, out var registration)) - return registration; - - throw new VContainerException(type, $"No such registration of type: {type}"); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool TryFindRegistration(Type type, out Registration registration) { @@ -228,7 +228,7 @@ internal Container(Registry registry, object applicationOrigin = null) [MethodImpl(MethodImplOptions.AggressiveInlining)] public object Resolve(Type type) { - if (registry.TryGet(type, out var registration)) + if (TryGetRegistration(type, out var registration)) { return Resolve(registration); } @@ -238,12 +238,12 @@ public object Resolve(Type type) [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryResolve(Type type, out object resolved) { - if (registry.TryGet(type, out var registration)) + if (TryGetRegistration(type, out var registration)) { resolved = Resolve(registration); return true; } - + resolved = default; return false; }