Added unit testing
This commit is contained in:
127
Syrette.Tests/ServiceContainerConstructorSelectionTests.cs
Normal file
127
Syrette.Tests/ServiceContainerConstructorSelectionTests.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
namespace Syrette.Tests;
|
||||
|
||||
public class ServiceContainerConstructorSelectionTests
|
||||
{
|
||||
public class CtorWithOptional
|
||||
{
|
||||
public ITestService? A { get; }
|
||||
public string? Name { get; }
|
||||
|
||||
public CtorWithOptional(ITestService a, string? name = "default")
|
||||
{
|
||||
A = a;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public class CtorWithExactMatch
|
||||
{
|
||||
public int Value { get; }
|
||||
|
||||
public CtorWithExactMatch(int value) { Value = value; }
|
||||
public CtorWithExactMatch(int value, string label) { Value = value; }
|
||||
}
|
||||
|
||||
public class NoSatisfiableCtor
|
||||
{
|
||||
public NoSatisfiableCtor(int value) { }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Greedy_picks_most_satisfiable_constructor()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
container.AddSingleton<ITestServiceB, TestServiceBImpl>();
|
||||
|
||||
container.AddSingleton<TestMultiCtor>();
|
||||
var instance = container.GetService<TestMultiCtor>();
|
||||
|
||||
Assert.NotNull(instance.A);
|
||||
Assert.NotNull(instance.B);
|
||||
Assert.Null(instance.C);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Greedy_picks_all_satisfied_over_partial()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
container.AddSingleton<ITestServiceB, TestServiceBImpl>();
|
||||
container.AddSingleton<ITestServiceC, TestServiceCImpl>();
|
||||
|
||||
container.AddSingleton<TestMultiCtor>();
|
||||
var instance = container.GetService<TestMultiCtor>();
|
||||
|
||||
Assert.NotNull(instance.A);
|
||||
Assert.NotNull(instance.B);
|
||||
Assert.NotNull(instance.C);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Greedy_falls_back_to_1_param_when_only_1_satisfiable()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
|
||||
container.AddSingleton<TestMultiCtor>();
|
||||
var instance = container.GetService<TestMultiCtor>();
|
||||
|
||||
Assert.NotNull(instance.A);
|
||||
Assert.Null(instance.B);
|
||||
Assert.Null(instance.C);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Optional_parameter_used_when_not_registered()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
container.AddSingleton<CtorWithOptional>();
|
||||
|
||||
var instance = container.GetService<CtorWithOptional>();
|
||||
Assert.NotNull(instance.A);
|
||||
Assert.Equal("default", instance.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Registration_args_satisfy_constructor()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<CtorWithExactMatch, CtorWithExactMatch>(42);
|
||||
|
||||
var instance = container.GetService<CtorWithExactMatch>();
|
||||
Assert.Equal(42, instance.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolution_args_satisfy_constructor()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<CtorWithExactMatch, CtorWithExactMatch>();
|
||||
|
||||
var instance = (CtorWithExactMatch)container.GetService(
|
||||
typeof(CtorWithExactMatch), new object[] { 99 });
|
||||
Assert.Equal(99, instance.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolution_args_override_registration_args()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<CtorWithExactMatch, CtorWithExactMatch>(10);
|
||||
|
||||
var instance = (CtorWithExactMatch)container.GetService(
|
||||
typeof(CtorWithExactMatch), new object[] { 20 });
|
||||
Assert.Equal(20, instance.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void No_suitable_constructor_throws()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<NoSatisfiableCtor>();
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
container.GetService<NoSatisfiableCtor>());
|
||||
}
|
||||
}
|
||||
40
Syrette.Tests/ServiceContainerDisposalTests.cs
Normal file
40
Syrette.Tests/ServiceContainerDisposalTests.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
namespace Syrette.Tests;
|
||||
|
||||
public class ServiceContainerDisposalTests
|
||||
{
|
||||
[Fact]
|
||||
public void Dispose_disposes_singletons_implementing_IDisposable()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<TestDisposableService>();
|
||||
var instance = container.GetService<TestDisposableService>();
|
||||
|
||||
container.Dispose();
|
||||
Assert.True(instance.IsDisposed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dispose_clears_singleton_cache()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<TestDisposableService>();
|
||||
container.GetService<TestDisposableService>();
|
||||
|
||||
container.Dispose();
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
container.GetService<TestDisposableService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Multiple_dispose_is_safe()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<TestDisposableService>();
|
||||
container.GetService<TestDisposableService>();
|
||||
|
||||
container.Dispose();
|
||||
container.Dispose();
|
||||
Assert.True(true);
|
||||
}
|
||||
}
|
||||
100
Syrette.Tests/ServiceContainerRegistrationTests.cs
Normal file
100
Syrette.Tests/ServiceContainerRegistrationTests.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
namespace Syrette.Tests;
|
||||
|
||||
public class ServiceContainerRegistrationTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddSingleton_TInterface_TImplementation_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
Assert.NotNull(container.GetService<ITestService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddSingleton_TInterface_TImplementation_with_args_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestDeepService>(Guid.NewGuid());
|
||||
Assert.NotNull(container.GetService<ITestService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddSingleton_TClass_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<TestServiceImpl>();
|
||||
Assert.NotNull(container.GetService<TestServiceImpl>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddSingleton_TClass_with_args_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<TestDeepService>(Guid.NewGuid());
|
||||
Assert.NotNull(container.GetService<TestDeepService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddTransient_TInterface_TImplementation_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<ITestService, TestServiceImpl>();
|
||||
Assert.NotNull(container.GetService<ITestService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddTransient_TInterface_TImplementation_with_args_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<ITestService, TestDeepService>(Guid.NewGuid());
|
||||
Assert.NotNull(container.GetService<ITestService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddTransient_TClass_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<TestServiceImpl>();
|
||||
Assert.NotNull(container.GetService<TestServiceImpl>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddTransient_TClass_with_args_registers_successfully()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<TestDeepService>(Guid.NewGuid());
|
||||
Assert.NotNull(container.GetService<TestDeepService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fluent_chaining_returns_same_container()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
var result = container
|
||||
.AddSingleton<ITestService, TestServiceImpl>()
|
||||
.AddTransient<TestServiceImpl>();
|
||||
Assert.Same(container, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Duplicate_registration_same_pair_throws()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
container.AddSingleton<ITestService, TestServiceImpl>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Duplicate_registration_different_impl_for_same_service_allowed()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
container.AddSingleton<ITestService, TestServiceAlt>();
|
||||
|
||||
var services = container.GetServiceTypes<ITestService>();
|
||||
Assert.Equal(2, services.Count);
|
||||
Assert.Contains(typeof(TestServiceImpl), services);
|
||||
Assert.Contains(typeof(TestServiceAlt), services);
|
||||
}
|
||||
}
|
||||
141
Syrette.Tests/ServiceContainerResolutionTests.cs
Normal file
141
Syrette.Tests/ServiceContainerResolutionTests.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
namespace Syrette.Tests;
|
||||
|
||||
public class ServiceContainerResolutionTests
|
||||
{
|
||||
[Fact]
|
||||
public void GetService_T_resolves_singleton()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
var instance = container.GetService<ITestService>();
|
||||
Assert.NotNull(instance);
|
||||
Assert.IsType<TestServiceImpl>(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetService_T_resolves_transient()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<ITestServiceB, TestServiceBImpl>();
|
||||
var instance = container.GetService<ITestServiceB>();
|
||||
Assert.NotNull(instance);
|
||||
Assert.IsType<TestServiceBImpl>(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Singleton_returns_same_instance()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
var a = container.GetService<ITestService>();
|
||||
var b = container.GetService<ITestService>();
|
||||
Assert.Same(a, b);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Transient_returns_new_instance()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<ITestServiceB, TestServiceBImpl>();
|
||||
var a = container.GetService<ITestServiceB>();
|
||||
var b = container.GetService<ITestServiceB>();
|
||||
Assert.NotSame(a, b);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetService_Type_non_generic_resolves()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
var instance = container.GetService(typeof(ITestService));
|
||||
Assert.NotNull(instance);
|
||||
Assert.IsType<TestServiceImpl>(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetService_Type_with_args_resolves()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<ITestService, TestDeepService>();
|
||||
var instance = container.GetService(typeof(ITestService), new object[] { Guid.NewGuid() });
|
||||
Assert.NotNull(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetService_T_throws_for_unregistered()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
container.GetService<ITestService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetService_Type_throws_for_unregistered()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
container.GetService(typeof(ITestService)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetService_returns_null_for_unregistered()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
var result = container.TryGetService(typeof(ITestService));
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetService_returns_instance_when_registered()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
var result = container.TryGetService(typeof(ITestService));
|
||||
Assert.NotNull(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolve_by_implementation_type_when_not_registered_directly()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
var instance = container.GetService(typeof(TestServiceImpl));
|
||||
Assert.NotNull(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolution_time_args_override_registration_time_args()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestDeepService>(Guid.Empty);
|
||||
var resolved = container.GetService(typeof(ITestService), new object[] { Guid.NewGuid() });
|
||||
Assert.NotNull(resolved);
|
||||
var deep = (TestDeepService)resolved;
|
||||
Assert.NotEqual(Guid.Empty, deep.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetServices_returns_all_registered_implementations()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
container.AddSingleton<ITestService, TestServiceAlt>();
|
||||
var services = container.GetServices<ITestService>();
|
||||
Assert.Equal(2, services.Count);
|
||||
var types = services.Select(s => s.GetType()).ToList();
|
||||
Assert.Contains(typeof(TestServiceImpl), types);
|
||||
Assert.Contains(typeof(TestServiceAlt), types);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetServiceTypes_returns_all_implementation_types()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
container.AddSingleton<ITestService, TestServiceAlt>();
|
||||
var types = container.GetServiceTypes<ITestService>();
|
||||
Assert.Equal(2, types.Count);
|
||||
Assert.Contains(typeof(TestServiceImpl), types);
|
||||
Assert.Contains(typeof(TestServiceAlt), types);
|
||||
}
|
||||
}
|
||||
61
Syrette.Tests/ServiceContainerThreadingTests.cs
Normal file
61
Syrette.Tests/ServiceContainerThreadingTests.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
namespace Syrette.Tests;
|
||||
|
||||
public class ServiceContainerThreadingTests
|
||||
{
|
||||
[Fact]
|
||||
public void Concurrent_singleton_resolution_returns_same_instance()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddSingleton<ITestService, TestServiceImpl>();
|
||||
|
||||
var results = new ITestService[10];
|
||||
|
||||
Parallel.For(0, 10, i =>
|
||||
{
|
||||
results[i] = container.GetService<ITestService>();
|
||||
});
|
||||
|
||||
for (int i = 1; i < results.Length; i++)
|
||||
{
|
||||
Assert.Same(results[0], results[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Concurrent_transient_resolution_returns_unique_instances()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
container.AddTransient<ITestService, TestServiceImpl>();
|
||||
|
||||
var results = new ITestService[10];
|
||||
|
||||
Parallel.For(0, 10, i =>
|
||||
{
|
||||
results[i] = container.GetService<ITestService>();
|
||||
});
|
||||
|
||||
for (int i = 0; i < results.Length; i++)
|
||||
{
|
||||
for (int j = i + 1; j < results.Length; j++)
|
||||
{
|
||||
Assert.NotSame(results[i], results[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Concurrent_registration_and_resolution_does_not_crash()
|
||||
{
|
||||
var container = new ServiceContainer();
|
||||
|
||||
Parallel.Invoke(
|
||||
() => { try { container.AddSingleton<ITestService, TestServiceImpl>(); } catch { } },
|
||||
() => { try { container.AddSingleton<ITestService, TestServiceImpl>(); } catch { } },
|
||||
() => { try { container.GetService<ITestService>(); } catch { } },
|
||||
() => { try { container.AddSingleton<ITestService, TestServiceImpl>(); } catch { } },
|
||||
() => { try { container.GetService<ITestService>(); } catch { } }
|
||||
);
|
||||
|
||||
Assert.NotNull(container);
|
||||
}
|
||||
}
|
||||
25
Syrette.Tests/Syrette.Tests.csproj
Normal file
25
Syrette.Tests/Syrette.Tests.csproj
Normal file
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TargetFrameworks>net10.0;net8.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syrette\Syrette.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
35
Syrette.Tests/TestTypes.cs
Normal file
35
Syrette.Tests/TestTypes.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace Syrette.Tests;
|
||||
|
||||
public interface ITestService { }
|
||||
public class TestServiceImpl : ITestService { }
|
||||
public class TestServiceAlt : ITestService { }
|
||||
|
||||
public interface ITestServiceB { }
|
||||
public class TestServiceBImpl : ITestServiceB { }
|
||||
|
||||
public interface ITestServiceC { }
|
||||
public class TestServiceCImpl : ITestServiceC { }
|
||||
|
||||
public class TestMultiCtor
|
||||
{
|
||||
public ITestService? A { get; }
|
||||
public ITestServiceB? B { get; }
|
||||
public ITestServiceC? C { get; }
|
||||
|
||||
public TestMultiCtor(ITestService a) { A = a; }
|
||||
public TestMultiCtor(ITestService a, ITestServiceB b) { A = a; B = b; }
|
||||
public TestMultiCtor(ITestService a, ITestServiceB b, ITestServiceC c) { A = a; B = b; C = c; }
|
||||
}
|
||||
|
||||
public class TestDeepService : ITestService
|
||||
{
|
||||
public Guid Id { get; }
|
||||
|
||||
public TestDeepService(Guid id) { Id = id; }
|
||||
}
|
||||
|
||||
public class TestDisposableService : IDisposable
|
||||
{
|
||||
public bool IsDisposed { get; private set; }
|
||||
public void Dispose() => IsDisposed = true;
|
||||
}
|
||||
10
Syrette.Tests/UnitTest1.cs
Normal file
10
Syrette.Tests/UnitTest1.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Syrette.Tests;
|
||||
|
||||
public class UnitTest1
|
||||
{
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
28
Syrette.sln
28
Syrette.sln
@@ -2,16 +2,44 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Syrette", "Syrette\Syrette.csproj", "{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Syrette.Tests", "Syrette.Tests\Syrette.Tests.csproj", "{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4730ABA2-3979-4B74-A3FF-042F6C3C47D6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CE07A0AF-1EAB-4AFF-B04F-16E0A8A5FC24}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -165,12 +165,12 @@ public class ServiceContainer : IDisposable {
|
||||
|
||||
if (descriptor.Lifetime == ServiceLifetime.Singleton) {
|
||||
lock (singletonLock) {
|
||||
if (singletons.TryGetValue(descriptor.ServiceType, out var singleton)) {
|
||||
if (singletons.TryGetValue(descriptor.ImplementationType, out var singleton)) {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
var instance = Instantiate(descriptor.ImplementationType, bestCtor, mergedArgs);
|
||||
singletons[descriptor.ServiceType] = instance;
|
||||
singletons[descriptor.ImplementationType] = instance;
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user