Somewhere it needs to make a database call. Maybe the simplest place would be in global.ascx if it's needed system wide.
private static ConcurrentDictionary<string, string> _tenantCache = new ConcurrentDictionary<string, string>();
protected virtual void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
var tenantId = _tenantCache.GetOrAdd(app.Context.Request.Url.Host, host =>
{
// Make database call in this class
var tenant = new TenantResolver();
return tenant.GetTenantId(host);
})
app.Context.Items["TenantID"] = tenantId ;
}
You will want to cache the result as Application_BeginRequest is called alot. You can then configure Unity to have child containers. Put all the common/default mappings in the parent container then create a child container per tenant and register the correct implementation for each tenant in it's own child container.
Then implement IDependencyResolver to return the correct child container.
public class TenantDependencyResolver : IDependencyResolver
{
private static IUnityContainer _parentContainer;
private static IDictionary<string, IUnityContainer> _childContainers = new Dictionary<string, IUnityContainer>();
public TenantDependencyResolver()
{
var fakeTenentID = "localhost";
var fakeTenentContainer = _parentContainer.CreateChildContainer();
// register any specific fakeTenent Interfaces to classes here
//Add the child container to the dictionary for use later
_childContainers[fakeTenentID] = fakeTenentContainer;
}
private IUnityContainer GetContainer()
{
var tenantID = HttpContext.Current.Items["TenantID"].ToString();
if (_childContainers.ContainsKey(tenantID)
{
return _childContainers[tenantID];
}
return _parentContainer;
}
public object GetService(Type serviceType)
{
var container = GetContainer();
return container.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
var container = GetContainer();
return container.ResolveAll(serviceType);
}
}
Then set ASP.NET MVC DependecyResolver to be the TenantDependencyResolver. I didn't run this code but it should give you an idea of what you would need to do. If your implementations are set then you might be able to do it in the static constructor of TenantDependecyResolver.