Skip to content

Commit 6819ab7

Browse files
authored
Merge pull request #634 from hadashiA/ku/improve-exists
Improve IContainerBuilder.Exists()
2 parents d2ed5ac + acd4fd2 commit 6819ab7

File tree

5 files changed

+83
-4
lines changed

5 files changed

+83
-4
lines changed

Diff for: .github/workflows/release.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ on:
1414

1515
env:
1616
GIT_TAG: ${{ github.event.inputs.tag }}
17-
17+
1818
jobs:
1919
update-version-number:
2020
uses: ./.github/workflows/update-version-number.yaml

Diff for: VContainer/Assets/Tests/ContainerBuilderTest.cs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using NUnit.Framework;
2+
3+
namespace VContainer.Tests
4+
{
5+
[TestFixture]
6+
public class ContainerBuilderTest
7+
{
8+
[Test]
9+
public void Exists()
10+
{
11+
var builder = new ContainerBuilder();
12+
builder.Register<ServiceA>(Lifetime.Singleton)
13+
.AsImplementedInterfaces()
14+
.AsSelf();
15+
16+
Assert.That(builder.Exists(typeof(ServiceA)), Is.True);
17+
Assert.That(builder.Exists(typeof(I4)), Is.False);
18+
Assert.That(builder.Exists(typeof(I4), includeInterfaceTypes: true), Is.True);
19+
}
20+
21+
[Test]
22+
public void Exists_FromChild()
23+
{
24+
var builder = new ContainerBuilder();
25+
builder.Register<ServiceA>(Lifetime.Singleton)
26+
.AsImplementedInterfaces()
27+
.AsSelf();
28+
29+
var parentScope = builder.Build();
30+
var childScope = parentScope.CreateScope(childBuilder =>
31+
{
32+
childBuilder.Register<ServiceB>(Lifetime.Singleton);
33+
34+
Assert.That(childBuilder.Exists(typeof(ServiceA)), Is.False);
35+
Assert.That(childBuilder.Exists(typeof(I4)), Is.False);
36+
Assert.That(childBuilder.Exists(typeof(I4), includeInterfaceTypes: true), Is.False);
37+
38+
Assert.That(childBuilder.Exists(typeof(ServiceA), findParentScopes: true), Is.True);
39+
Assert.That(childBuilder.Exists(typeof(I4), findParentScopes: true), Is.False);
40+
Assert.That(childBuilder.Exists(typeof(I4), findParentScopes: true, includeInterfaceTypes: true), Is.True);
41+
42+
Assert.That(childBuilder.Exists(typeof(ServiceB)), Is.True);
43+
});
44+
}
45+
}
46+
}

Diff for: VContainer/Assets/Tests/ContainerBuilderTest.cs.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: VContainer/Assets/VContainer/Runtime/Container.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ public interface IObjectResolver : IDisposable
2828
object Resolve(Registration registration);
2929
IScopedObjectResolver CreateScope(Action<IContainerBuilder> installation = null);
3030
void Inject(object instance);
31+
bool TryGetRegistration(Type type, out Registration registration);
3132
}
3233

3334
public interface IScopedObjectResolver : IObjectResolver
3435
{
3536
IObjectResolver Root { get; }
3637
IScopedObjectResolver Parent { get; }
37-
bool TryGetRegistration(Type type, out Registration registration);
3838
}
3939

4040
public enum Lifetime
@@ -224,6 +224,11 @@ public void Inject(object instance)
224224
injector.Inject(instance, this, null);
225225
}
226226

227+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
228+
public bool TryGetRegistration(Type type, out Registration registration)
229+
=> registry.TryGet(type, out registration);
230+
231+
227232
[MethodImpl(MethodImplOptions.AggressiveInlining)]
228233
public void Dispose()
229234
{

Diff for: VContainer/Assets/VContainer/Runtime/ContainerBuilder.cs

+27-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public interface IContainerBuilder
1818

1919
T Register<T>(T registrationBuilder) where T : RegistrationBuilder;
2020
void RegisterBuildCallback(Action<IObjectResolver> container);
21-
bool Exists(Type type, bool includeInterfaceTypes = false);
21+
bool Exists(Type type, bool includeInterfaceTypes = false, bool findParentScopes = false);
2222
}
2323

2424
public sealed class ScopedContainerBuilder : ContainerBuilder
@@ -44,6 +44,31 @@ public IScopedObjectResolver BuildScope()
4444

4545
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4646
public override IObjectResolver Build() => BuildScope();
47+
48+
public override bool Exists(Type type, bool includeInterfaceTypes = false, bool findParentScopes = false)
49+
{
50+
if (base.Exists(type, includeInterfaceTypes, findParentScopes))
51+
{
52+
return true;
53+
}
54+
55+
if (findParentScopes)
56+
{
57+
var next = parent;
58+
while (next != null)
59+
{
60+
if (parent.TryGetRegistration(type, out var registration))
61+
{
62+
if (includeInterfaceTypes || registration.ImplementationType == type)
63+
{
64+
return true;
65+
}
66+
}
67+
next = next.Parent;
68+
}
69+
}
70+
return false;
71+
}
4772
}
4873

4974
public class ContainerBuilder : IContainerBuilder
@@ -87,7 +112,7 @@ public void RegisterBuildCallback(Action<IObjectResolver> callback)
87112
}
88113

89114
[MethodImpl(MethodImplOptions.AggressiveInlining)]
90-
public bool Exists(Type type, bool includeInterfaceTypes = false)
115+
public virtual bool Exists(Type type, bool includeInterfaceTypes = false, bool findParentScopes = false)
91116
{
92117
foreach (var registrationBuilder in registrationBuilders)
93118
{

0 commit comments

Comments
 (0)