mercredi 5 août 2009

Singleton réutilisable dépendant d'un context Http

Salut à tous,

Après avoir lu le post d'Ayende Rahien, je me suis dit qu'il fallait que je partage l'implémentation de mon module de singleton http que j'utilise depuis un certain temps maintenant. Ce module me permet avec très peu de lignes de codd d'avoir une seule instance de ce que je veux. Si comme Ayende, vous utilisez NHibernate, vous avez seulement d'hériter du code que je vais vous donner pour faire votre propre HttpSessionModule, et ainsi avoir une session créée HttpContext. Je l'utilise pour avoir non pas un ObjectContext (j'utilise euss), mais un service qui cache cette couche de persistence.

Voici l'implémentation abstraite de mon module de singleton Http :


public abstract class HttpSingletonModule<T> : IHttpModule
{
#region IHttpModule Members

public void Dispose()
{
}

public void Init(HttpApplication application)
{
application.PostAuthorizeRequest += new EventHandler(application_AuthorizeRequest);
application.EndRequest += new EventHandler(application_EndRequest);
}

void application_EndRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
HttpContext context = application.Context;
if (context != null)
{
T instance = (T)context.Items[typeof(T).AssemblyQualifiedName];
if (instance is IDisposable)
((IDisposable)instance).Dispose();
}
}

public static T Instance
{
get { return (T)HttpContext.Current.Items[typeof(T).AssemblyQualifiedName]; }
set { HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = value; }
}

void application_AuthorizeRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
HttpContext context = application.Context;
if (context != null)
context.Items.Add(typeof(T).AssemblyQualifiedName, CreateInstance(context));
}

protected abstract T CreateInstance(HttpContext context);

#endregion
}


Comme vous devez l'avoir compris maintenant, pour implémenter un module, c'est assez simple. Voici l'implémentation que j'utilise dans un projet :


public class PortalServiceModule : HttpSingletonModule<PortalService>
{
protected override PortalService CreateInstance(HttpContext context)
{
if (context.User.Identity.IsAuthenticated)
return new PortalService(context.User.Identity.Name);
return new PortalService();
}
}

Vous voyez ? Si peu de lignes de code pour une telle simplicité d'utilisation : pour récupérer l'instance de mon PortalService, j'ai juste à appeler la propriété static Instance de mon PortalServiceModule. Comment pourrait-on faire plus simple ?