Is there a way to set the active tenant on a child scope? I assumed it would have a global affect but it does not after the child scope (ILifetimeScope
) has been resolved.
<package id="Autofac" version="4.9.2" targetFramework="net471" />
<package id="Autofac.Multitenant" version="4.2.0" targetFramework="net471" />
Reproduction written using a .net framework console application and the above listed dependencies.
using Autofac;
using Autofac.Multitenant;
namespace ConsoleAutoFacTenants
{
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<GeneralReader>().As<IReader>().InstancePerDependency();
var appContainer = builder.Build();
var tenantIdentifier = new AutomationTenantStrategy();
var mtc = new MultitenantContainer(tenantIdentifier, appContainer);
mtc.ConfigureTenant("1", b => b.RegisterType<SpecificReader>().As<IReader>().InstancePerDependency());
// expected
var reader1 = mtc.Resolve<IReader>();
System.Diagnostics.Debug.Assert(reader1.Name == "General");
// unexpected result in debug.assert, assumed that reader2 would resolve type SpecificReader
var childScoped = mtc.BeginLifetimeScope();
tenantIdentifier.TenantId = "1";
var reader2 = childScoped.Resolve<IReader>();
System.Diagnostics.Debug.Assert(reader2.Name == "Specific");
}
}
internal sealed class AutomationTenantStrategy : ITenantIdentificationStrategy
{
public object TenantId { get; set; }
public bool TryIdentifyTenant(out object tenantId)
{
var activeTenant = this.TenantId;
if (TenantId == null)
{
tenantId = null;
return false;
}
tenantId = activeTenant;
return true;
}
}
public interface IReader
{
string Name { get; }
}
public sealed class GeneralReader : IReader
{
public string Name => "General";
}
public sealed class SpecificReader : IReader
{
public string Name => "Specific";
}
}
When you resolve a ILifetimeScope
from a scope it will return itself and not create a child lifetimescope.
This line :
var childScoped = mtc.Resolve<ILifetimeScope>();
should be replaced by
var childScoped = mtc.BeginLifetimeScope();
When a new LifetimeScope is created the multitenant module will set the tenantId to the scope. In your sample you have to "change" the tenantId before the creation of the child LifetimeScope
tenantIdentifier.TenantId = "1";
var childScoped = mtc.BeginLifetimeScope();
The resolved IReader
will then be the one specified for the tenant.