StructureMap singleton changing by argument?

Using StructureMap, is it possible to have a singleton object for each argument value? For example, let's say I want to maintain a separate singleton for each website in a multi-user web application:

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

I want to support another singleton object corresponding to each site:

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

Currently, it seems that every time I try to enable ISiteSettings, a new object is created.

+4
source share
2 answers

The Singleton scope really means singleton — there can only be one instance. For your scenario, I would recommend that you implement a custom ILifecycle that uses requestHost (which I suppose can be pulled from the HttpContext) to return the corresponding cached instance. Take a look at the source code of StructureMap to see how other ILifecycles are implemented.

When you register For<ISiteSettings> , you can specify your own ILifecycle, instead of using one of the built-in.

+4
source

Thanks Joshua, I accepted your advice. Here the solution I ended up with seems to work fine. Any feedback is 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>() ); 
+5
source

All Articles