Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 1c4c4fd

Browse files
committed
Merge branch 'release/0.1.0'
2 parents 58f969f + 407e70a commit 1c4c4fd

File tree

5 files changed

+279
-27
lines changed

5 files changed

+279
-27
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using SimpleInjector;
5+
6+
using Spectre.Console.Cli;
7+
8+
namespace Spectre.Console.Registrars.SimpleInjector.Tests
9+
{
10+
internal class RegistrarFixture
11+
{
12+
private readonly List<Action<Container>> containerActions = new List<Action<Container>>();
13+
private readonly List<Action<ITypeRegistrar>> registrarActions = new List<Action<ITypeRegistrar>>();
14+
private Lifestyle lifestyle;
15+
private Type[] multiRegistrationTypes;
16+
17+
internal void GivenLifestyle(Lifestyle lifestyle)
18+
{
19+
this.lifestyle = lifestyle;
20+
}
21+
22+
internal void GivenMultiRegistrationTypes(params Type[] multiRegistrationTypes)
23+
{
24+
this.multiRegistrationTypes = multiRegistrationTypes;
25+
}
26+
27+
internal void GivenOnContainer(Action<Container> action)
28+
{
29+
containerActions.Add(action);
30+
}
31+
32+
internal void GivenOnRegistrar(Action<ITypeRegistrar> action)
33+
{
34+
registrarActions.Add(action);
35+
}
36+
37+
internal ITypeResolver GetResolver()
38+
{
39+
var container = new Container();
40+
foreach (var action in containerActions)
41+
{
42+
action(container);
43+
}
44+
45+
var registrar = new SimpleInjectorRegistrar(container, lifestyle, multiRegistrationTypes);
46+
foreach (var action in registrarActions)
47+
{
48+
action(registrar);
49+
}
50+
51+
return registrar.Build();
52+
}
53+
}
54+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
using System;
2+
3+
using Shouldly;
4+
5+
using Xunit;
6+
7+
namespace Spectre.Console.Registrars.SimpleInjector.Tests
8+
{
9+
public class RegistrarTests
10+
{
11+
[Fact]
12+
public void Resolver_Resolving_null_Throws()
13+
{
14+
var fixture = new RegistrarFixture();
15+
var resolver = fixture.GetResolver();
16+
17+
Action action = () => resolver.Resolve(null);
18+
19+
action.ShouldThrow<ArgumentNullException>();
20+
}
21+
22+
[Fact]
23+
public void Resolver_Should_Return_Registration_From_Container()
24+
{
25+
var fixture = new RegistrarFixture();
26+
fixture.GivenOnContainer(c => c.Register<ISomeInterface, SomeDependency>());
27+
28+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
29+
30+
actual.ShouldNotBeNull();
31+
actual.ShouldBeOfType<SomeDependency>();
32+
}
33+
34+
[Fact]
35+
public void Resolver_Should_Return_Registration_From_Registrar()
36+
{
37+
var fixture = new RegistrarFixture();
38+
fixture.GivenOnRegistrar(r => r.Register(typeof(ISomeInterface), typeof(SomeDependency)));
39+
40+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
41+
42+
actual.ShouldNotBeNull();
43+
actual.ShouldBeOfType<SomeDependency>();
44+
}
45+
46+
[Fact]
47+
public void Resolver_Should_Return_Instance_From_Registrar()
48+
{
49+
var fixture = new RegistrarFixture();
50+
var expected = new SomeDependency();
51+
fixture.GivenOnRegistrar(r => r.RegisterInstance(typeof(ISomeInterface), expected));
52+
53+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
54+
55+
actual.ShouldNotBeNull();
56+
ReferenceEquals(expected, actual).ShouldBeTrue();
57+
}
58+
59+
[Fact]
60+
public void Resolver_Should_Return_Lazy_From_Registrar()
61+
{
62+
var fixture = new RegistrarFixture();
63+
var expected = new SomeDependency();
64+
fixture.GivenOnRegistrar(r => r.RegisterLazy(typeof(ISomeInterface), () => expected));
65+
66+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
67+
68+
actual.ShouldNotBeNull();
69+
ReferenceEquals(expected, actual).ShouldBeTrue();
70+
}
71+
72+
[Fact]
73+
public void Resolver_Resolving_From_Multiple_Lazies_Returns_The_Last_Registration()
74+
{
75+
var fixture = new RegistrarFixture();
76+
fixture.GivenMultiRegistrationTypes(typeof(ISomeInterface));
77+
fixture.GivenOnRegistrar(r => r.RegisterLazy(typeof(ISomeInterface), () => new SomeDependency()));
78+
fixture.GivenOnRegistrar(r => r.RegisterLazy(typeof(ISomeInterface), () => new SomeOtherDependency()));
79+
80+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
81+
82+
actual.ShouldNotBeNull();
83+
actual.ShouldBeOfType<SomeOtherDependency>();
84+
}
85+
86+
[Fact(Skip = "Doesn't work at the moment")]
87+
public void Resolver_Should_Not_Call_Lazy_Factory_If_Not_Needed()
88+
{
89+
var fixture = new RegistrarFixture();
90+
var factoryCalled = false;
91+
fixture.GivenOnRegistrar(r => r.RegisterLazy(typeof(ISomeInterface), () =>
92+
{
93+
factoryCalled = true;
94+
return new SomeDependency();
95+
}));
96+
97+
fixture.GetResolver();
98+
99+
factoryCalled.ShouldBeFalse();
100+
}
101+
102+
[Fact]
103+
public void Resolver_Registering_Multiple_Does_Not_Throw()
104+
{
105+
var fixture = new RegistrarFixture();
106+
fixture.GivenMultiRegistrationTypes(typeof(ISomeInterface));
107+
fixture.GivenOnRegistrar(r => r.Register(typeof(ISomeInterface), typeof(SomeDependency)));
108+
fixture.GivenOnRegistrar(r => r.Register(typeof(ISomeInterface), typeof(SomeOtherDependency)));
109+
110+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
111+
112+
actual.ShouldNotBeNull();
113+
}
114+
115+
[Fact]
116+
public void Resolver_Resolving_From_Multiple_Returns_The_Last_Registration()
117+
{
118+
var fixture = new RegistrarFixture();
119+
fixture.GivenMultiRegistrationTypes(typeof(ISomeInterface));
120+
fixture.GivenOnRegistrar(r => r.Register(typeof(ISomeInterface), typeof(SomeDependency)));
121+
fixture.GivenOnRegistrar(r => r.Register(typeof(ISomeInterface), typeof(SomeOtherDependency)));
122+
123+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
124+
125+
actual.ShouldNotBeNull();
126+
actual.ShouldBeOfType<SomeOtherDependency>();
127+
}
128+
129+
[Fact]
130+
public void Resolver_Resolving_From_Multiple_Instances_Returns_The_Last_Registration()
131+
{
132+
var fixture = new RegistrarFixture();
133+
fixture.GivenMultiRegistrationTypes(typeof(ISomeInterface));
134+
fixture.GivenOnRegistrar(r => r.RegisterInstance(typeof(ISomeInterface), new SomeDependency()));
135+
fixture.GivenOnRegistrar(r => r.RegisterInstance(typeof(ISomeInterface), new SomeOtherDependency()));
136+
137+
var actual = fixture.GetResolver().Resolve(typeof(ISomeInterface));
138+
139+
actual.ShouldNotBeNull();
140+
actual.ShouldBeOfType<SomeOtherDependency>();
141+
}
142+
143+
private interface ISomeInterface
144+
{
145+
}
146+
147+
private class SomeDependency : ISomeInterface
148+
{
149+
}
150+
151+
private class SomeOtherDependency : ISomeInterface
152+
{
153+
}
154+
}
155+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="coverlet.msbuild" Version="3.1.0">
9+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
10+
<PrivateAssets>all</PrivateAssets>
11+
</PackageReference>
12+
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" />
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
14+
<PackageReference Include="Moq" Version="4.16.1" />
15+
<PackageReference Include="Shouldly" Version="4.0.3" />
16+
<PackageReference Include="SimpleInjector" Version="5.3.2" />
17+
<PackageReference Include="Spectre.Console" Version="0.41.0" />
18+
<PackageReference Include="xunit" Version="2.4.1" />
19+
<PackageReference Include="xunit.analyzers" Version="0.10.0" />
20+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
22+
<PrivateAssets>all</PrivateAssets>
23+
</PackageReference>
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<ProjectReference Include="..\Spectre.Console.Registrars.SimpleInjector\Spectre.Console.Registrars.SimpleInjector.csproj" />
28+
</ItemGroup>
29+
30+
</Project>

src/Spectre.Console.Registrars.SimpleInjector.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30114.105
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spectre.Console.Registrars.SimpleInjector", "Spectre.Console.Registrars.SimpleInjector\Spectre.Console.Registrars.SimpleInjector.csproj", "{3C1439A7-B1E2-4321-9878-68376D7048FC}"
77
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spectre.Console.Registrars.SimpleInjector.Tests", "Spectre.Console.Registrars.SimpleInjector.Tests\Spectre.Console.Registrars.SimpleInjector.Tests.csproj", "{A9545423-59A6-43C7-BC0B-A2F775E5AD0F}"
9+
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1012
Debug|Any CPU = Debug|Any CPU
@@ -18,5 +20,9 @@ Global
1820
{3C1439A7-B1E2-4321-9878-68376D7048FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
1921
{3C1439A7-B1E2-4321-9878-68376D7048FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
2022
{3C1439A7-B1E2-4321-9878-68376D7048FC}.Release|Any CPU.Build.0 = Release|Any CPU
23+
{A9545423-59A6-43C7-BC0B-A2F775E5AD0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24+
{A9545423-59A6-43C7-BC0B-A2F775E5AD0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
25+
{A9545423-59A6-43C7-BC0B-A2F775E5AD0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
26+
{A9545423-59A6-43C7-BC0B-A2F775E5AD0F}.Release|Any CPU.Build.0 = Release|Any CPU
2127
EndGlobalSection
2228
EndGlobal

src/Spectre.Console.Registrars.SimpleInjector/SimlpeInjectorRegistrar.cs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@
33
using SimpleInjector;
44
using Spectre.Console.Cli;
55

6-
namespace Spectre.Console.Registrars.SimpleInjector
6+
// ReSharper disable once CheckNamespace
7+
namespace Spectre.Console
78
{
89
/// <summary>
910
/// Implements <see cref="ITypeRegistrar"/> using a SimpleInjector <see cref="Container"/>.
1011
/// </summary>
1112
public class SimpleInjectorRegistrar : ITypeRegistrar
1213
{
13-
private readonly Container _container;
14-
private readonly Lifestyle _lifestyle;
15-
private readonly Type[] _multiRegistrationTypes;
14+
private readonly Container container;
15+
private readonly Lifestyle lifestyle;
16+
private readonly Type[] multiRegistrationTypes;
1617

1718
/// <summary>
1819
/// Constructs a new instance using the the given <see cref="Container" />.
@@ -29,13 +30,13 @@ public class SimpleInjectorRegistrar : ITypeRegistrar
2930
/// <param name="multiRegistrationTypes">List of types that are to be registered multiple times.
3031
/// Default is [ <see cref="ICommand{TSettings}"/>, <see cref="ICommand"/> ].</param>
3132
/// <exception cref="ArgumentNullException"></exception>
32-
public SimpleInjectorRegistrar(Container container,
33+
public SimpleInjectorRegistrar(Container container,
3334
Lifestyle lifestyle = null,
3435
Type[] multiRegistrationTypes = null)
3536
{
36-
_container = container ?? throw new ArgumentNullException(nameof(container));
37-
_lifestyle = lifestyle ?? Lifestyle.Singleton;
38-
_multiRegistrationTypes = multiRegistrationTypes ?? new[]
37+
this.container = container ?? throw new ArgumentNullException(nameof(container));
38+
this.lifestyle = lifestyle ?? Lifestyle.Singleton;
39+
this.multiRegistrationTypes = multiRegistrationTypes ?? new[]
3940
{
4041
typeof(ICommand),
4142
typeof(ICommand<>)
@@ -45,55 +46,57 @@ public SimpleInjectorRegistrar(Container container,
4546
/// <inheritdoc cref="ITypeRegistrar.Register"/>
4647
public void Register(Type service, Type implementation)
4748
{
48-
if (_multiRegistrationTypes.Contains(service))
49+
if (multiRegistrationTypes.Contains(service))
4950
{
50-
_container.Collection.Append(service, implementation, _lifestyle);
51+
container.Collection.Append(service, implementation, lifestyle);
5152
return;
5253
}
5354

54-
_container.Register(service, implementation, _lifestyle);
55+
container.Register(service, implementation, lifestyle);
5556
}
5657

5758
/// <inheritdoc cref="ITypeRegistrar.RegisterInstance"/>
5859
public void RegisterInstance(Type service, object implementation)
5960
{
60-
if (_multiRegistrationTypes.Contains(service))
61+
if (multiRegistrationTypes.Contains(service))
6162
{
62-
_container.Collection.AppendInstance(service, implementation);
63+
container.Collection.AppendInstance(service, implementation);
6364
return;
6465
}
65-
66-
_container.RegisterInstance(service, implementation);
66+
67+
container.RegisterInstance(service, implementation);
6768
}
6869

6970
/// <inheritdoc cref="ITypeRegistrar.RegisterLazy"/>
7071
public void RegisterLazy(Type service, Func<object> factory)
7172
{
7273
// todo: non of these code-paths are lazy!!
73-
if (_multiRegistrationTypes.Contains(service))
74+
if (multiRegistrationTypes.Contains(service))
7475
{
75-
// todo: this ignores the lifestyle, but seemingly Func<object> can not be used on collections.
76-
_container.Collection.AppendInstance(service, factory());
76+
var registration = lifestyle.CreateRegistration(service, factory, container);
77+
container.Collection.Append(service, registration);
7778
return;
7879
}
79-
80-
_container.Register(service, factory, _lifestyle);
80+
81+
container.Register(service, factory, lifestyle);
8182
}
8283

8384
/// <inheritdoc cref="ITypeRegistrar.Build"/>
8485
public ITypeResolver Build()
8586
{
86-
_container.Verify();
87-
return new SimpleInjectorTypeResolver(_container);
87+
container.Verify();
88+
return new SimpleInjectorTypeResolver(container, multiRegistrationTypes);
8889
}
8990

9091
private class SimpleInjectorTypeResolver : ITypeResolver
9192
{
92-
private readonly Container _container;
93+
private readonly Container container;
94+
private readonly Type[] multiRegistrationTypes;
9395

94-
public SimpleInjectorTypeResolver(Container container)
96+
public SimpleInjectorTypeResolver(Container container, Type[] multiRegistrationTypes)
9597
{
96-
_container = container;
98+
this.container = container;
99+
this.multiRegistrationTypes = multiRegistrationTypes;
97100
}
98101

99102
public object Resolve(Type type)
@@ -103,8 +106,12 @@ public object Resolve(Type type)
103106
throw new ArgumentNullException(nameof(type));
104107
}
105108

106-
return _container.GetInstance(type);
109+
var implementation = multiRegistrationTypes.Contains(type)
110+
? container.GetAllInstances(type).LastOrDefault()
111+
: container.GetInstance(type);
112+
113+
return implementation;
107114
}
108115
}
109116
}
110-
}
117+
}

0 commit comments

Comments
 (0)