Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange behavior with ChildLifetimeScope, IEnumerable and Singleton. #697

Closed
Akeit0 opened this issue Jul 30, 2024 · 2 comments
Closed

Strange behavior with ChildLifetimeScope, IEnumerable and Singleton. #697

Akeit0 opened this issue Jul 30, 2024 · 2 comments

Comments

@Akeit0
Copy link
Contributor

Akeit0 commented Jul 30, 2024

First, I prepared these classes.

public class A
{
    static int instanceCount = 0;
    readonly int instanceId = instanceCount++;
    public override string ToString()
    {
        return $"A {instanceId}";
    }
}
public class BaseLifetimeScope : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        builder.Register<A>(Lifetime.Singleton).AsSelf();
        builder.RegisterBuildCallback(x =>
        {
               Debug.Log("BaseLifetimeScope "+x.Resolve<A>());
        });
    }
}
public class ChildLifetimeScope : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        builder.RegisterBuildCallback(resolver =>
        {
            Debug.Log("ChildLifetimeScope "+string.Join(",", resolver.Resolve<IEnumerable<A>>()));
        });
    }
}

Log

BaseLifetimeScope A 0
ChildLifetimeScope A 0

This seems fine.

But, when I changed the ChildLifetimeScope as follows

public class ChildLifetimeScope : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        builder.Register<A>(Lifetime.Singleton).AsSelf();// I changed this part.
        
        builder.RegisterBuildCallback(resolver =>
        {
            Debug.Log("ChildLifetimeScope "+string.Join(",", resolver.Resolve<IEnumerable<A>>()));
        });
    }
}

logs changed to

BaseLifetimeScope A 0
ChildLifetimeScope A 1,A 2

.
I assumed It would be like ChildLifetimeScope A 1,A 0.

I don't know what the intended behavior is, but I don't think the result is intended.

@hadashiA
Copy link
Owner

hadashiA commented Aug 7, 2024

Thanks for the report. it is strange..

📝
Internally, the key of the ConcurrentDictionary holding the Singleton is Registration, but when multiple registrations are found in the parent and child, the keys don't match, so it looks like they are duplicate instantiated.

@hadashiA
Copy link
Owner

Fixed in #698 .

Now the behavior is as follows.

  • If a Singleton of the same type is registered for each Parent/Child, each container can have an instance. (This has been the specification for some time.)
  • In this case, when Child resolves IEnumerable, it searches for an instance of each Parent/Child. That is, the number of elements will be 2
    • If Singleton already exists in Parent, it is used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants