Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructureMap singletons varying by argument?

Using StructureMap, is it possible to have a singleton object for each value of an argument? For example, say I want to maintain a different singleton for each website in a multi-tenancy web app:

For<ISiteSettings>().Singleton().Use<SiteSettings>();

I want to maintain a different singleton object corresponding to each site:

ObjectFactory.With<string>(requestHost).GetInstance<ISiteSettings>();

Currently, it seems to create a new object every time I try to resolve ISiteSettings.

like image 344
Chris Fulstow Avatar asked Jan 22 '23 13:01

Chris Fulstow


1 Answers

Thanks Joshua, I took your advice. Here's the solution I finished up with, which seems to work fine. Any feedback appreciated.

public class TenantLifecycle : ILifecycle
{
    private readonly ConcurrentDictionary<string, MainObjectCache> _tenantCaches =
        new ConcurrentDictionary<string, MainObjectCache>();

    public IObjectCache FindCache()
    {
        var cache = _tenantCaches.GetOrAdd(TenantKey, new MainObjectCache());
        return cache;
    }

    public void EjectAll()
    {
        FindCache().DisposeAndClear();
    }

    public string Scope
    {
        get { return "Tenant"; }
    }

    protected virtual string TenantKey
    {
        get
        {
            var requestHost = HttpContext.Current.Request.Url.Host;
            var normalisedRequestHost = requestHost.ToLowerInvariant();
            return normalisedRequestHost;
        }
    }
}

With StructureMap configuration:

ObjectFactory.Initialize(
    x => x.For<ISiteSettings>()
        .LifecycleIs(new TenantLifecycle())
        .Use<SiteSettings>()
);
like image 84
Chris Fulstow Avatar answered Jan 31 '23 19:01

Chris Fulstow