autofac/Autofac.Extensions.DependencyInjection

Making IServiceScopeFactory singleton breaks mutitenant registrations

me-viper opened this issue · 2 comments

Describe the bug
Fix for issue #83 breaks Autofac.Multitenant.RegistrationExtensions.InstancePerTenant registrations.

InstancePerTenant relies on ILifetimeScope with Tag="tenantLifetime" being present in resolution chain.
When IServiceScopeFactory was transient Autofac.Integration.AspNetCore.Multitenant.MultitenantRequestServicesMiddleware resolved new IServiceScopeFactory from MultitenantContainer.GetCurrentTenantScope() thus there was ILifetimeScope with Tag="tenantLifetime" in the resolution chain. Making it singleton breaks this behavior.

public async Task Invoke(HttpContext context)
{
	if (_contextAccessor.HttpContext == null)
	{
		_contextAccessor.HttpContext = context;
	}

	IServiceProvidersFeature existingFeature = null!;
	try
	{
               // Parent scope for IServiceScopeFactory here should be MultitenantContainer.GetCurrentTenantScope() rather than root.
		var autofacFeature = RequestServicesFeatureFactory.CreateFeature(context, _multitenantContainer.Resolve<IServiceScopeFactory>());

		...
}
internal class X
{
}

internal class TenantIdentificationStrategy : ITenantIdentificationStrategy
{
    public bool TryIdentifyTenant(out object tenantId)
    {
        tenantId = "default";
        return true;
    }
}

[Test]
public void ScopeResolution()
{
    var sc = new ServiceCollection();
    
    var builder = new ContainerBuilder();
    builder.Populate(sc);
    builder.RegisterType<X>().InstancePerTenant();

    // Override AutofacServiceScopeFactory to be transient and tast passes.
    // builder.RegisterType<AutofacServiceScopeFactory>().As<IServiceScopeFactory>();

    var container = builder.Build();
    var tenantContainer = new MultitenantContainer(new TenantIdentificationStrategy(), container);

    var scope = tenantContainer.Resolve<IServiceScopeFactory>();

    var result = scope.CreateScope().ServiceProvider.GetRequiredService<X>();
}

Assembly/dependency versions:

<PackageReference Include="Autofac" Version="6.4.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Autofac.Multitenant" Version="6.0.0" />

Thanks for reporting this. We are aware of this issue and are already working on it. There is a ticket and PR over at the repository of the integration package:

autofac/Autofac.AspNetCore.Multitenant#44 (comment)