TenantDistributor
public sealed class TenantDistributor : ITenantDistributor, IStashboxContainer, IDependencyRegistrator, IDependencyResolver, IServiceProvider, IAsyncDisposable, IDisposable, IDependencyReMapper, IDependencyCollectionRegistrator, IDecoratorRegistrator, IFuncRegistrator
Represents a tenant distributor that manages tenants in a multi-tenant environment.
using Stashbox.Configuration;
using Stashbox.Registration;
using Stashbox.Registration.Fluent;
using Stashbox.Resolution;
using Stashbox.Utils;
using Stashbox.Utils.Data;
using Stashbox.Utils.Data.Immutable;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Stashbox.Multitenant
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public sealed class TenantDistributor : ITenantDistributor, IStashboxContainer, IDependencyRegistrator, IDependencyResolver, IServiceProvider, IAsyncDisposable, IDisposable, IDependencyReMapper, IDependencyCollectionRegistrator, IDecoratorRegistrator, IFuncRegistrator
{
private int disposed;
private ImmutableTree<object, IStashboxContainer> tenantRepository = ImmutableTree<object, IStashboxContainer>.Empty;
private readonly IStashboxContainer rootContainer;
public IContainerContext ContainerContext => rootContainer.ContainerContext;
[System.Runtime.CompilerServices.NullableContext(2)]
public TenantDistributor(IStashboxContainer rootContainer = null)
{
this.rootContainer = (rootContainer ?? new StashboxContainer(null));
}
public void ConfigureTenant(object tenantId, Action<IStashboxContainer> tenantConfig)
{
IStashboxContainer stashboxContainer = CreateChildContainer(null);
if (Swap.SwapValue<object, IStashboxContainer, byte, byte, ImmutableTree<object, IStashboxContainer>>(ref tenantRepository, (object id, IStashboxContainer container, byte _, byte _, ImmutableTree<object, IStashboxContainer> repo) => repo.AddOrUpdate(id, container, false, false), tenantId, stashboxContainer, 0, 0)) {
tenantConfig(stashboxContainer);
ContainerContext.RootScope.AddDisposableTracking(stashboxContainer);
}
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public IDependencyResolver GetTenant(object tenantId)
{
return tenantRepository.GetOrDefaultByValue(tenantId);
}
public void RegisterResolver(IResolver resolver)
{
rootContainer.RegisterResolver(resolver);
}
public IStashboxContainer CreateChildContainer([System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<ContainerConfigurator> config = null)
{
return rootContainer.CreateChildContainer(config);
}
[System.Runtime.CompilerServices.NullableContext(2)]
public bool IsRegistered<TFrom>(object name = null)
{
return rootContainer.IsRegistered<TFrom>(name);
}
public bool IsRegistered(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name = null)
{
return rootContainer.IsRegistered(typeFrom, name);
}
public void Configure(Action<ContainerConfigurator> config)
{
rootContainer.Configure(config);
}
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 (ReadOnlyKeyValue<object, IStashboxContainer> item in tenantRepository.Walk()) {
try {
item.Value.Validate();
} catch (AggregateException ex2) {
expandableArray.Add(new AggregateException($"""{item.Key}""", ex2.InnerExceptions));
}
}
if (expandableArray.Length > 0)
throw new AggregateException("Tenant distributor validation failed. See the inner exceptions for details.", expandableArray);
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0,
1,
1
})]
public IEnumerable<KeyValuePair<Type, ServiceRegistration>> GetRegistrationMappings()
{
return rootContainer.GetRegistrationMappings();
}
public IEnumerable<RegistrationDiagnosticsInfo> GetRegistrationDiagnostics()
{
return rootContainer.GetRegistrationDiagnostics();
}
public void Dispose()
{
if (Interlocked.CompareExchange(ref disposed, 1, 0) == 0)
rootContainer.Dispose();
}
public ValueTask DisposeAsync()
{
if (Interlocked.CompareExchange(ref disposed, 1, 0) == 0)
return rootContainer.DisposeAsync();
return new ValueTask(Task.CompletedTask);
}
public IStashboxContainer Register<TFrom, TTo>(Action<RegistrationConfigurator<TFrom, TTo>> configurator) where TFrom : class where TTo : class, TFrom
{
return rootContainer.Register(configurator);
}
public IStashboxContainer Register<TFrom, TTo>([System.Runtime.CompilerServices.Nullable(2)] object name = null) where TFrom : class where TTo : class, TFrom
{
return rootContainer.Register<TFrom, TTo>(name);
}
public IStashboxContainer Register<TFrom>(Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<RegistrationConfigurator<TFrom, TFrom>> configurator = null) where TFrom : class
{
return rootContainer.Register(typeTo, configurator);
}
public IStashboxContainer Register(Type typeFrom, Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<RegistrationConfigurator> configurator = null)
{
return rootContainer.Register(typeFrom, typeTo, configurator);
}
public IStashboxContainer Register<TTo>(Action<RegistrationConfigurator<TTo, TTo>> configurator) where TTo : class
{
return ((IDependencyRegistrator)rootContainer).Register<TTo>(configurator);
}
public IStashboxContainer Register<TTo>([System.Runtime.CompilerServices.Nullable(2)] object name = null) where TTo : class
{
return rootContainer.Register<TTo>(name);
}
public IStashboxContainer Register(Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<RegistrationConfigurator> configurator = null)
{
return rootContainer.Register(typeTo, configurator);
}
public IStashboxContainer RegisterSingleton<TFrom, TTo>([System.Runtime.CompilerServices.Nullable(2)] object name = null) where TFrom : class where TTo : class, TFrom
{
return rootContainer.RegisterSingleton<TFrom, TTo>(name);
}
public IStashboxContainer RegisterSingleton<TTo>([System.Runtime.CompilerServices.Nullable(2)] object name = null) where TTo : class
{
return rootContainer.RegisterSingleton<TTo>(name);
}
public IStashboxContainer RegisterSingleton(Type typeFrom, Type typeTo, [System.Runtime.CompilerServices.Nullable(2)] object name = null)
{
return rootContainer.RegisterSingleton(typeFrom, typeTo, name);
}
public IStashboxContainer RegisterScoped<TFrom, TTo>([System.Runtime.CompilerServices.Nullable(2)] object name = null) where TFrom : class where TTo : class, TFrom
{
return rootContainer.RegisterScoped<TFrom, TTo>(name);
}
public IStashboxContainer RegisterScoped(Type typeFrom, Type typeTo, [System.Runtime.CompilerServices.Nullable(2)] object name = null)
{
return rootContainer.RegisterScoped(typeFrom, typeTo, name);
}
public IStashboxContainer RegisterScoped<TTo>([System.Runtime.CompilerServices.Nullable(2)] object name = null) where TTo : class
{
return rootContainer.RegisterScoped<TTo>(name);
}
public IStashboxContainer RegisterInstance<TInstance>(TInstance instance, [System.Runtime.CompilerServices.Nullable(2)] object name = null, bool withoutDisposalTracking = false, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<TInstance> finalizerDelegate = null) where TInstance : class
{
return rootContainer.RegisterInstance(instance, name, withoutDisposalTracking, finalizerDelegate);
}
public IStashboxContainer RegisterInstance(object instance, Type serviceType, [System.Runtime.CompilerServices.Nullable(2)] object name = null, bool withoutDisposalTracking = false)
{
return rootContainer.RegisterInstance(instance, serviceType, name, withoutDisposalTracking);
}
public IStashboxContainer WireUp<TInstance>(TInstance instance, [System.Runtime.CompilerServices.Nullable(2)] object name = null, bool withoutDisposalTracking = false, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<TInstance> finalizerDelegate = null) where TInstance : class
{
return rootContainer.WireUp(instance, name, withoutDisposalTracking, finalizerDelegate);
}
public IStashboxContainer WireUp(object instance, Type serviceType, [System.Runtime.CompilerServices.Nullable(2)] object name = null, bool withoutDisposalTracking = false)
{
return rootContainer.WireUp(instance, serviceType, name, withoutDisposalTracking);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public object GetService(Type serviceType)
{
return rootContainer.GetService(serviceType);
}
public object Resolve(Type typeFrom)
{
return rootContainer.Resolve(typeFrom);
}
public object Resolve(Type typeFrom, object[] dependencyOverrides)
{
return rootContainer.Resolve(typeFrom, dependencyOverrides);
}
public object Resolve(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name)
{
return rootContainer.Resolve(typeFrom, name);
}
public object Resolve(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name, object[] dependencyOverrides)
{
return rootContainer.Resolve(typeFrom, name, dependencyOverrides);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public object ResolveOrDefault(Type typeFrom)
{
return rootContainer.ResolveOrDefault(typeFrom);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public object ResolveOrDefault(Type typeFrom, object[] dependencyOverrides)
{
return rootContainer.ResolveOrDefault(typeFrom, dependencyOverrides);
}
[System.Runtime.CompilerServices.NullableContext(2)]
public object ResolveOrDefault([System.Runtime.CompilerServices.Nullable(1)] Type typeFrom, object name)
{
return rootContainer.ResolveOrDefault(typeFrom, name);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public object ResolveOrDefault(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name, object[] dependencyOverrides)
{
return rootContainer.ResolveOrDefault(typeFrom, name, dependencyOverrides);
}
public IEnumerable<TKey> ResolveAll<[System.Runtime.CompilerServices.Nullable(2)] TKey>()
{
return rootContainer.ResolveAll<TKey>();
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: System.Runtime.CompilerServices.Nullable(1)]
public IEnumerable<TKey> ResolveAll<TKey>(object name)
{
return rootContainer.ResolveAll<TKey>(name);
}
public IEnumerable<TKey> ResolveAll<[System.Runtime.CompilerServices.Nullable(2)] TKey>(object[] dependencyOverrides)
{
return rootContainer.ResolveAll<TKey>(dependencyOverrides);
}
public IEnumerable<TKey> ResolveAll<[System.Runtime.CompilerServices.Nullable(2)] TKey>([System.Runtime.CompilerServices.Nullable(2)] object name, object[] dependencyOverrides)
{
return rootContainer.ResolveAll<TKey>(name, dependencyOverrides);
}
public IEnumerable<object> ResolveAll(Type typeFrom)
{
return rootContainer.ResolveAll(typeFrom);
}
public IEnumerable<object> ResolveAll(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name)
{
return rootContainer.ResolveAll(typeFrom, name);
}
public IEnumerable<object> ResolveAll(Type typeFrom, object[] dependencyOverrides)
{
return rootContainer.ResolveAll(typeFrom, dependencyOverrides);
}
public IEnumerable<object> ResolveAll(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name, object[] dependencyOverrides)
{
return rootContainer.ResolveAll(typeFrom, name, dependencyOverrides);
}
public Delegate ResolveFactory(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name = null, params Type[] parameterTypes)
{
return rootContainer.ResolveFactory(typeFrom, name, parameterTypes);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public Delegate ResolveFactoryOrDefault(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name = null, params Type[] parameterTypes)
{
return rootContainer.ResolveFactoryOrDefault(typeFrom, name, parameterTypes);
}
public IDependencyResolver BeginScope([System.Runtime.CompilerServices.Nullable(2)] object name = null, bool attachToParent = false)
{
return rootContainer.BeginScope(name, attachToParent);
}
public void PutInstanceInScope(Type typeFrom, object instance, bool withoutDisposalTracking = false, [System.Runtime.CompilerServices.Nullable(2)] object name = null)
{
rootContainer.PutInstanceInScope(typeFrom, instance, withoutDisposalTracking, name);
}
public TTo BuildUp<TTo>(TTo instance) where TTo : class
{
return rootContainer.BuildUp(instance);
}
public object Activate(Type type, params object[] arguments)
{
return rootContainer.Activate(type, arguments);
}
public ValueTask InvokeAsyncInitializers(CancellationToken token = default(CancellationToken))
{
return rootContainer.InvokeAsyncInitializers(token);
}
[System.Runtime.CompilerServices.NullableContext(2)]
public bool CanResolve<TFrom>(object name = null)
{
return rootContainer.CanResolve<TFrom>(name);
}
public bool CanResolve(Type typeFrom, [System.Runtime.CompilerServices.Nullable(2)] object name = null)
{
return rootContainer.CanResolve(typeFrom, name);
}
public IEnumerable<DelegateCacheEntry> GetDelegateCacheEntries()
{
return rootContainer.GetDelegateCacheEntries();
}
public IStashboxContainer ReMap<TFrom, TTo>([System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<RegistrationConfigurator<TFrom, TTo>> configurator = null) where TFrom : class where TTo : class, TFrom
{
return rootContainer.ReMap(configurator);
}
public IStashboxContainer ReMap<TFrom>(Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<RegistrationConfigurator<TFrom, TFrom>> configurator = null) where TFrom : class
{
return rootContainer.ReMap(typeTo, configurator);
}
public IStashboxContainer ReMap(Type typeFrom, Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<RegistrationConfigurator> configurator = null)
{
return rootContainer.ReMap(typeFrom, typeTo, configurator);
}
public IStashboxContainer ReMap<TTo>([System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<RegistrationConfigurator<TTo, TTo>> configurator = null) where TTo : class
{
return ((IDependencyReMapper)rootContainer).ReMap<TTo>(configurator);
}
public IStashboxContainer ReMapDecorator(Type typeFrom, Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<DecoratorConfigurator> configurator = null)
{
return rootContainer.ReMapDecorator(typeFrom, typeTo, configurator);
}
public IStashboxContainer ReMapDecorator<TFrom, TTo>([System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<DecoratorConfigurator<TFrom, TTo>> configurator = null) where TFrom : class where TTo : class, TFrom
{
return rootContainer.ReMapDecorator(configurator);
}
public IStashboxContainer ReMapDecorator<TFrom>(Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<DecoratorConfigurator<TFrom, TFrom>> configurator = null) where TFrom : class
{
return rootContainer.ReMapDecorator(typeTo, configurator);
}
public IStashboxContainer RegisterTypesAs(Type typeFrom, IEnumerable<Type> types, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Func<Type, bool> selector = null, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<RegistrationConfigurator> configurator = null)
{
return rootContainer.RegisterTypesAs(typeFrom, types, selector, configurator);
}
public IStashboxContainer RegisterTypes(IEnumerable<Type> types, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Func<Type, bool> selector = null, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})] Func<Type, Type, bool> serviceTypeSelector = null, bool registerSelf = true, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<RegistrationConfigurator> configurator = null)
{
return rootContainer.RegisterTypes(types, selector, serviceTypeSelector, registerSelf, configurator);
}
public IStashboxContainer ComposeBy(Type compositionRootType, params object[] compositionRootArguments)
{
return rootContainer.ComposeBy(compositionRootType, compositionRootArguments);
}
public IStashboxContainer ComposeBy(ICompositionRoot compositionRoot)
{
return rootContainer.ComposeBy(compositionRoot);
}
public IStashboxContainer RegisterDecorator(Type typeFrom, Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<DecoratorConfigurator> configurator = null)
{
return rootContainer.RegisterDecorator(typeFrom, typeTo, configurator);
}
public IStashboxContainer RegisterDecorator<TFrom, TTo>([System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<DecoratorConfigurator<TFrom, TTo>> configurator = null) where TFrom : class where TTo : class, TFrom
{
return rootContainer.RegisterDecorator(configurator);
}
public IStashboxContainer RegisterDecorator(Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] Action<DecoratorConfigurator> configurator = null)
{
return rootContainer.RegisterDecorator(typeTo, configurator);
}
public IStashboxContainer RegisterDecorator<TTo>([System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<DecoratorConfigurator<TTo, TTo>> configurator = null) where TTo : class
{
return ((IDecoratorRegistrator)rootContainer).RegisterDecorator<TTo>(configurator);
}
public IStashboxContainer RegisterDecorator<TFrom>(Type typeTo, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1,
1
})] Action<DecoratorConfigurator<TFrom, TFrom>> configurator = null) where TFrom : class
{
return rootContainer.RegisterDecorator(typeTo, configurator);
}
public IStashboxContainer RegisterFunc<[System.Runtime.CompilerServices.Nullable(2)] TService>(Func<IDependencyResolver, TService> factory, [System.Runtime.CompilerServices.Nullable(2)] object name = null)
{
return rootContainer.RegisterFunc(factory, name);
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: System.Runtime.CompilerServices.Nullable(1)]
public IStashboxContainer RegisterFunc<T1, TService>([System.Runtime.CompilerServices.Nullable(1)] Func<T1, IDependencyResolver, TService> factory, object name = null)
{
return rootContainer.RegisterFunc(factory, name);
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: System.Runtime.CompilerServices.Nullable(1)]
public IStashboxContainer RegisterFunc<T1, T2, TService>([System.Runtime.CompilerServices.Nullable(1)] Func<T1, T2, IDependencyResolver, TService> factory, object name = null)
{
return rootContainer.RegisterFunc(factory, name);
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: System.Runtime.CompilerServices.Nullable(1)]
public IStashboxContainer RegisterFunc<T1, T2, T3, TService>([System.Runtime.CompilerServices.Nullable(1)] Func<T1, T2, T3, IDependencyResolver, TService> factory, object name = null)
{
return rootContainer.RegisterFunc(factory, name);
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: System.Runtime.CompilerServices.Nullable(1)]
public IStashboxContainer RegisterFunc<T1, T2, T3, T4, TService>([System.Runtime.CompilerServices.Nullable(1)] Func<T1, T2, T3, T4, IDependencyResolver, TService> factory, object name = null)
{
return rootContainer.RegisterFunc(factory, name);
}
}
}