grumpydev/TinyIoC

Problem understanding ResolveAll<T> with ChildContainer Registrations

bytefish opened this issue · 2 comments

I am trying to understand how to use child containers with TinyIoCContainer.

I have a Parent Container, where I register the interface AnInterface with the implementation A. Then I open up a child container and register the interface AnInterface with the implementation B.

I would expect, that ResolveAll<AnInterface> on the child container returns either A and B (because I don't expect the child container to override the parent containers registrations), or only A or only B. I don't know what the actual expectation here is. But the actual result of ResolveAll returns the type B two times, which doesn't make much sense to me.

Or is it the expected outcome?

The Test case, that fails for me:

[Test]
public void ChildContainerResolveAll()
{
    using (var container = new TinyIoCContainer())
    {
        container.Register<AnInterface, A>();
        using (var childContainer = container.GetChildContainer())
        {
            childContainer.Register<AnInterface, B>();

            var registeredTypes = childContainer.ResolveAll<AnInterface>();

            Assert.AreEqual(2, registeredTypes.Count());

            Assert.IsTrue(registeredTypes.Any(x => x.GetType() == typeof(A)));
            Assert.IsTrue(registeredTypes.Any(x => x.GetType() == typeof(B)));
        }
    }
}

I observe the same behaviour @bytefish mentions. When a parent and child container hold a registration for an identical type-name combination, ResolveAll<T> on the child container returns two instances of the child's registration (two instances of what would be obtained by calling Resolve<T>() on the child container).

The behaviour when using Resolve<>() rather than ResolveAll<>() is that a child container's identical type-name registration would hide the parent's. This can be seen in the test ChildContainerResolve_TypeRegisteredWithParentAndChild_ResolvesChildVersion(). Let's call this principle [*] "type-name-matching child registrations should override/supersede/replace/hide parent ones".

If we assume this principle [*] should still hold/should not break when moving to ResolveAll<>(), we would expect ResolveAll<>() in this scenario to return a single instance of the child container's registration (and not return the parent's registration at all; it is overridden by the child's).

I will shortly submit a PR for this.

👍