dadhi / DryIoc

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

Transient resolve with opening scope using factory func in singleton #507

Closed BinaryCraX closed 2 years ago

BinaryCraX commented 2 years ago

When a transient service (which has openResolutionScope set) gets resolved using a factory-func from inside another service which has Reuse.Singleton set, then this resolve won't open a new scope as I would expected.

Is this behavior the desired behavior and I am just using it wrong?

[TestFixture]
class Transient_resolve_with_scope_using_factory_func_in_singleton
{
    [Test]
    public void Example()
    {
        var container = new Container(rules => rules
            .WithTrackingDisposableTransients()
        );

        container.Register<Bar>(Reuse.Singleton); // if "Reuse.Singleton" gets removed, the scope ist opened (and injected as part of IResolverContext) as expected.
        container.Register<IFoo, Foo>(setup: Setup.With(openResolutionScope: true));

        container.Register<Dependency>(Reuse.ScopedTo<IFoo>());

        var bar = container.Resolve<Bar>();
        bar.DoStuffWithFoo();
    }

    class Bar
    {
        private readonly Func<IFoo> fooFactory;
        private IFoo foo;

        public void DoStuffWithFoo()
        {
            foo = fooFactory(); // expecting this to open a scope.
            foo.Dispose();
        }

        public Bar(Func<IFoo> fooFactory)
        {
            this.fooFactory = fooFactory;
        }
    }

    interface IFoo : IDisposable
    {
        Dependency Dep { get; }
    }

    class Foo : IFoo
    {
        public Dependency Dep { get; }

        private readonly IResolverContext _scope;
        public Foo(Dependency dep, IResolverContext scope)
        {
            Dep = dep;
            _scope = scope;

            Assert.IsTrue(scope.CurrentScope != null, "Expected to have a scope.");
        }

        public void Dispose() => _scope.Dispose();
    }

    class Dependency : IDisposable
    {
        public bool IsDisposed { get; private set; }
        public void Dispose() => IsDisposed = true;
    }
}

Used DryIoc-Version: 5.1.0

dadhi commented 2 years ago

@BinaryCraX Interesting, will look.

dadhi commented 2 years ago

@BinaryCraX v5.2.0 with the fix is out.

BinaryCraX commented 2 years ago

Thank you very much :)