4

En utilisant StructureMap, est-il possible d'avoir un objet singleton pour chaque valeur d'un argument? Par exemple, que je veux maintenir un autre singleton pour chaque site dans une application web multi-location:StructureMap singletons variant par argument?

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

Je veux maintenir un autre objet singleton correspondant à chaque site:

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

Actuellement, il semble créer un nouvel objet chaque fois que j'essaie de résoudre ISiteSettings.

Répondre

4

La portée Singleton signifie vraiment singleton - il ne peut y avoir qu'une seule instance. Pour votre scénario, je vous recommande d'implémenter un ILifecycle personnalisé qui utilise l'hôte requestHost (que je suppose pouvoir être extrait de HttpContext) pour renvoyer l'instance mise en cache appropriée. Jetez un oeil au code source de StructureMap pour voir comment les autres ILifecycles sont implémentés.

Lorsque vous vous inscrivez For<ISiteSettings>, il y a une option pour spécifier votre propre ILifecycle, au lieu d'utiliser l'un des plus intégrés.

5

Merci Joshua, j'ai pris vos conseils. Voici la solution que j'ai trouvée, qui semble fonctionner correctement. Tout commentaire apprécié.

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; 
     } 
    } 
} 

Avec configuration StructureMap:

ObjectFactory.Initialize(
    x => x.For<ISiteSettings>() 
     .LifecycleIs(new TenantLifecycle()) 
     .Use<SiteSettings>() 
); 
+0

Utilisez une variante de celui-ci où la location est déterminée à partir de la chaîne de requête, fonctionne très bien. –

+0

Pourquoi _tenantCaches n'est pas statique dans cette implémentation? Si j'appelle le nouveau TenantLifecycle() dans différents mappages "For", j'obtiendrai de nouveaux caches d'objet? –