Skip to content

Commit

Permalink
Enumerable can create more than one instance of PerResolve
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed May 16, 2024
1 parent c7014dd commit 51e02fa
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 7 deletions.
8 changes: 1 addition & 7 deletions src/Pure.DI.Core/Core/Code/BlockCodeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,7 @@ public void Build(BuildContext ctx, in Block block)
var level = ctx.Level;
var isThreadSafe = ctx.DependencyGraph.Source.Hints.IsThreadSafeEnabled;
var lockIsRequired = ctx.LockIsRequired ?? isThreadSafe;
var toCheckExistence =
// The "singleton" or "scoped" instance must be created with a check each time
variable.Node.Lifetime is Lifetime.Singleton or Lifetime.Scoped
|| variable.Node.Lifetime == Lifetime.Scoped
// The "per resolve" instance should be created without checks if it is the only one in the composition
|| (variable.Node.Lifetime == Lifetime.PerResolve && variable.Info.RefCount > 1);

var toCheckExistence = variable.Node.Lifetime is Lifetime.Singleton or Lifetime.Scoped or Lifetime.PerResolve;
var uniqueAccumulators = ctx.Accumulators
.Where(accumulator => !accumulator.IsDeclared)
.GroupBy(i => i.Name)
Expand Down
69 changes: 69 additions & 0 deletions tests/Pure.DI.IntegrationTests/LifetimesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1897,4 +1897,73 @@ public static void Main()
result.Success.ShouldBeTrue(result);
result.StdOut.ShouldBe(["True", "True", "True", "True", "True", "True", "False", "True", "True"], result);
}

[Theory]
[InlineData("Singleton")]
[InlineData("Scoped")]
[InlineData("PerResolve")]
public async Task ShouldSupportSingletonScopedPerResolveInEnumerable(string lifetime)
{
// Given

// When
var result = await $$"""
using System;
using Pure.DI;
using System.Collections.Generic;
namespace Sample
{
interface IService {};
class StagingService : IService
{
public StagingService() => Console.WriteLine(GetType());
}
class RegistrationService : IService
{
public RegistrationService() => Console.WriteLine(GetType());
}
class ServiceHost
{
public ServiceHost(IEnumerable<IService> services)
{
foreach (var service in services)
{
}
foreach (var service in services)
{
}
}
}
static class Setup
{
private static void SetupComposition()
{
DI.Setup(nameof(Composition))
.Bind(1).As(Lifetime.#Lifetime).To<StagingService>()
.Bind(2).As(Lifetime.PerResolve).To<RegistrationService>()
.Root<ServiceHost>("Host");
}
}
public class Program
{
public static void Main()
{
var composition = new Composition();
var Host = composition.Host;
}
}
}
""".Replace("#Lifetime", lifetime).RunAsync();

// Then
result.Success.ShouldBeTrue(result);
result.StdOut.ShouldBe(["Sample.StagingService", "Sample.RegistrationService"], result);
}
}

0 comments on commit 51e02fa

Please sign in to comment.