Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="3.6.4-preview-646" />

 TenantDistributor

Represents a tenant distributor that manages tenants in a multitenant environment.
using Stashbox.Utils; using Stashbox.Utils.Data; using Stashbox.Utils.Data.Immutable; using System; using System.Threading; namespace Stashbox.Multitenant { public class TenantDistributor : ITenantDistributor, IDisposable { private int disposed; private ImmutableTree<object, IStashboxContainer> tenantRepository = ImmutableTree<object, IStashboxContainer>.Empty; public IStashboxContainer RootContainer { get; } public TenantDistributor(IStashboxContainer rootContainer = null) { RootContainer = (rootContainer ?? new StashboxContainer(null)); } public void ConfigureTenant(object tenantId, Func<IStashboxContainer, IDisposable> tenantConfig) { Shield.EnsureNotNull(tenantId, "tenantId"); Shield.EnsureNotNull(tenantConfig, "tenantConfig"); IStashboxContainer stashboxContainer = RootContainer.CreateChildContainer(null); if (Swap.SwapValue<object, IStashboxContainer, byte, byte, ImmutableTree<object, IStashboxContainer>>(ref tenantRepository, (object id, IStashboxContainer container, byte t3, byte t4, ImmutableTree<object, IStashboxContainer> repo) => repo.AddOrUpdate(id, container, false, false), tenantId, stashboxContainer, 0, 0)) { IDisposable disposable = tenantConfig(stashboxContainer); RootContainer.ContainerContext.RootScope.AddDisposableTracking(disposable); } } public IDependencyResolver GetTenant(object tenantId) { Shield.EnsureNotNull(tenantId, "tenantId"); return tenantRepository.GetOrDefaultByValue(tenantId); } public void Validate() { ExpandableArray<Exception> expandableArray = new ExpandableArray<Exception>(); try { RootContainer.Validate(); } catch (AggregateException ex) { expandableArray.Add(new AggregateException("Root container validation failed. See the inner exceptions for details.", ex.InnerExceptions)); } foreach (KeyValue<object, IStashboxContainer> item in tenantRepository.Walk()) { try { item.Value.Validate(); } catch (AggregateException ex2) { expandableArray.Add(new AggregateException($"""{new object[1] { item.Key }}""", ex2.InnerExceptions)); } } if (expandableArray.Length > 0) throw new AggregateException("Tenant distributor validation failed. See the inner exceptions for details.", expandableArray); } public void Dispose() { if (Interlocked.CompareExchange(ref disposed, 1, 0) == 0) RootContainer.Dispose(); } } }