dadhi / DryIoc

DryIoc is fast, small, full-featured IoC Container for .NET
MIT License
1.01k stars 123 forks source link

Use not working for scoped type after having resolved it in another scope #550

Closed HugoLemieux closed 1 year ago

HugoLemieux commented 1 year ago

Hi, If I try to replace a scoped dependency of a scoped type inside a scope after having resolved the same scoped type in another scope before, it returns the same dependency of the type returned in the previous scope.

It is not doing this if I do not resolve the scoped type in another scope before.

Here's a test class reproducing both cases: `using DryIoc;

namespace DryIocScopedType {

[TestClass]
public class ScopedTypeTests
{
    private interface IScopedTypeDependency { }
    private class DefaultScopedTypeDependency: IScopedTypeDependency { }
    private class AnotherScopedTypeDependency : IScopedTypeDependency { }
    private class ScopedType 
    {
        public IScopedTypeDependency Dependency { get; set; }
        public ScopedType( IScopedTypeDependency dependency )
        {
            Dependency = dependency;
        }
    }

    private Container _container;

    [TestInitialize]
    public void Setup()
    {
        _container = new Container();
        _container.Register<ScopedType>( Reuse.Scoped );
        _container.Register<IScopedTypeDependency, DefaultScopedTypeDependency>( Reuse.Scoped );
    }

    [TestCleanup]
    public void TearDown()
    {
        _container.Dispose();
    }

    [TestMethod]
    public void Resolve_WithoutResolveInAnotherScopeBefore_Succeed()
    {
        ScopedType scopedTypeObj;
        var dependency = new AnotherScopedTypeDependency();
        using ( var scope = _container.OpenScope() )
        {
            scope.Use<IScopedTypeDependency>( dependency );
            scopedTypeObj = scope.Resolve<ScopedType>();
        }
        Assert.AreSame( scopedTypeObj.Dependency, dependency );
    }

    [TestMethod]
    public void Resolve_WithResolveInAnotherScopeBefore_Fail()
    {
        ScopedType scopedTypeObj;
        var dependency = new AnotherScopedTypeDependency();
        using ( var scope1 = _container.OpenScope() )
            scope1.Resolve<ScopedType>();
        using ( var scope2 = _container.OpenScope() )
        {
            scope2.Use<IScopedTypeDependency>( dependency );
            scopedTypeObj = scope2.Resolve<ScopedType>();
        }
        Assert.AreSame( scopedTypeObj.Dependency, dependency );
    }
}

}`

How can I replace scoped dependencies when their scoped dependent types could have been resolved in others scopes before?

Regards,

dadhi commented 1 year ago

Hi, thanks for the tests. I will check what's happening here.

dadhi commented 1 year ago

@HugoLemieux

In order to fix the thing, you need to add the setup: Setup.With(asResolutionCall: true) to the dependency as following:

        public void Resolve_WithResolveInAnotherScopeBefore_Fail()
        {
            var container = new Container();
            container.Register<ScopedType>(Reuse.Scoped);
            container.Register<IScopedTypeDependency, DefaultScopedTypeDependency>(
                Reuse.Scoped,
                setup: Setup.With(asResolutionCall: true)); // fixes the thing

            ScopedType scopedTypeObj;
            using (var scope1 = container.OpenScope())
                scope1.Resolve<ScopedType>();

            var dependency = new AnotherScopedTypeDependency();
            using (var scope2 = container.OpenScope())
            {
                scope2.Use<IScopedTypeDependency>(dependency);
                scopedTypeObj = scope2.Resolve<ScopedType>();
            }

            Assert.AreSame(scopedTypeObj.Dependency, dependency);
        }

The reason is explained here: https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/RulesAndDefaultConventions.md#injecting-dependency-asresolutioncall