The ASP.NET Singleton-per-Request pattern
Lately I needed to have an instance of a class to be unique for a certain amount of time, that is, one instance only of that class should exist for that time interval in my app domain.
In these cases what comes to my mind is the
Singleton Design Pattern, which imposes that one instance only of a class can be loaded into an app domain and is alive as long as the app domain is.
My problem was that I needed that object to be unique only for a small time interval, which later I identified as being the life of a single request. That's when I recalled of a very useful IDictionary collection whose lifetime corresponds to the request-response cycle, and where you can store items which are then available during all the stages of the pipeline. This object is the
Items instance property of the
HttpContext class, and is defined as following:
System.Collections.IDictionary HttpContext.Items
Let me say it again: into this collection you can store items that are then made available during all the request-response process, and are unique to that particular request-response. To enfore this and make it even clearer, the description of this object as given by the intellisense is:
Gets a key/value collection that can be used to organize and share data between
an System.Web.IHttpModule interface and an System.Web.IHttpHandler interface
during an HTTP request.You understand how powerful this object is, and the ASP.NET engine uses this mechanism itself to mantain some state information, like the session id and something more.
Going back to my problem, what I wanted to achieve is a lazy load (created only when necessary) instance of a class being unique to my request, so I came up with this code.
public class SingletonPerRequest
{
public static SingletonPerRequest Current
{
get
{
return (HttpContext.Current.Items["SingletonPerRequest"] ??
(HttpContext.Current.Items["SingletonPerRequest"] =
new SingletonPerRequest())) as SingletonPerRequest;
}
}
}
which can be used calling the static
Current property of the class. What this code does is check if an instance of the class is already in the Items collection. In that case, it returns a reference to that instance, otherwise a new instance is created and placed in the Items collection, so that the next time it is requested during this same request it's already there.
Note that here we don't need any synchronization mechanism, since a single request is not executed
concurrently by more than one thread.