unitycontainer / microsoft-dependency-injection

Unity.Microsoft.DependencyInjection package
Apache License 2.0
63 stars 36 forks source link

A scoped service added only to a nested container is resolvable through a non-related nested container #88

Open Amleto opened 3 years ago

Amleto commented 3 years ago

Scenario: Root container with two child containers (siblings). A scoped service is added to one of the child containers. The service should only be resolvable from the child container in which it was registered.

This is the case in the following test, using IServiceProviderFactory<IUnityContainer>.CreateBuilder(...)

[Fact]
public void ScopedServiceOnlyResolvedFromChildContainer_using_CreateBuilder()
{
    var container = new UnityContainer();
    var factory = new ServiceProviderFactory(container);
    var unityFactory = (IServiceProviderFactory<IUnityContainer>) factory;

    var childServices = new ServiceCollection();
    childServices.AddScoped<SampleClass>();
    var childContainerA = unityFactory.CreateBuilder(childServices);
    var childContainerB = unityFactory.CreateBuilder(new ServiceCollection());

    Assert.True(childContainerA.IsRegistered<SampleClass>());
    Assert.False(childContainerB.IsRegistered<SampleClass>());
}

However, the following test using ServiceProviderFactory.CreateServiceProvider(...) fails. This is not expected.

[Fact]
public void ScopedServiceOnlyResolvedFromChildContainer_using_CreateServiceProvider_serviceCollection()
{
    var container = new UnityContainer();
    var factory = new ServiceProviderFactory(container);

    var childServices = new ServiceCollection();
    childServices.AddScoped<SampleClass>();
    var childContainerA = factory.CreateServiceProvider(childServices);
    var childContainerB = factory.CreateServiceProvider(new ServiceCollection());

    Assert.NotNull(childContainerA.GetService<SampleClass>());
    Assert.Null(childContainerB.GetService<SampleClass>()); // << container B also resolves the service, failing the test.
}

For reference,

private class SampleClass
        {
        }