Update: This doesn’t work gracefully. I worked on this a little more and tried using it, made some semantic improvements, but I don’t think C#/.NET supports what I’m trying to do. If I could just find a way to convert a given type, including generic types, into a unique string representation, it could be nice. Calling object’s ToString doesn’t serialize type parameters of generics. =( I guess if you’re willing to have only one instance per generic family, this would work gracefully. But that’s a major concession to me. Getting around this by deriving types from generic instances is not graceful either.
I know it’s been a while, so I figured I’d break the silence with an entry that I’m sure will enthrall all of you: how to create an immutable singleton per request in ASP.NET! Whoo! And if you make it to the end, I reveal some juicy gossip and deep dark secrets about myself.
The singleton pattern, of course, refers to a class of which only one object instantiation can exist within a running program (i.e. an application domain in the .NET framework). See the Wikipedia article for details. To create a singelton whose instantiability is bounded by an ASP.NET request rather than the CLR application domain, you basically leverage the Items collection in HttpContext. See this for details. That’s all fine, good, spiffy, and all that, but what about when you want the singleton to be immutable? That is, you want the members to be initialized when the singleton is instantiated, and you want to enforce immutability on them thereafter. What do you do?
Well, at first I thought about the readonly member modifier, which allows write access to the member from the constructor only. Unfortunately, singleton construction is handled within the singleton instance accessor. This lazy-loading doesn’t support parameterized construction. In other words, how would you get the initialization data into the accessor so it can provide it to the constructor? You can’t.
Next, I considered using an “isInitialized” static boolean member, which would be initialized to false, and would flip once the member variables were initialized. But this seemed to be too much of a compromise, because I would be breaking the required “immutability” semantics since initialization obviously requires mutability. I wanted to stick with initialization occurring at instantiation.
So I thought about it more and decided that the instantation did not need to occur implicitly in the accessor. Instead, the accessor would return either the instance if it exists, or null. A static Initialize() method, which would accept initialization data, would then handle the instantiation. If Initialize() had already been called, an exception would be thrown. Ka-boom!
Before I present my reference implementation, I should note that the instance variables need to be immutable themselves. In the .NET framework, value types and some reference types (e.g. strings) are immutable, but most reference types are not. So if your singleton composes reference types, you need to design them to be immutable themselves (and then you pass the already-constructed reference type variable into Initialize()). See this for details.
(I’ve generalized my reference implementation, for added Wow factor. WOW! This makes it really easy to create a write-protected singleton of any class. The generalization clunkily requires that the type parameter expose a string property to differentiate itself in the HttpContext.)
And now the code you’ve all been waiting for:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
namespace ScrambledBrains.Nuggets
{
// immutable modification of singleton-per-request pattern
public class ImmutableRequestSingleton<ImmutableType> where ImmutableType : IIdentifiable, new()
{
protected static string _identifier = ”ImmutableRequestSingleton<“;
private ImmutableRequestSingleton() { }
public static void Initialize(ImmutableType immutableReferenceMember)
{
if (HttpContext.Current.Items[_identifier + (new ImmutableType()).TypeIdentity] == null) // then ImmutableRequestSingleton is uninitialized
{
HttpContext.Current.Items[_identifier + new ImmutableType().TypeIdentity] = new ImmutableRequestSingleton<ImmutableType>();
((ImmutableRequestSingleton<ImmutableType>)(HttpContext.Current.Items[_identifier + new ImmutableType().TypeIdentity]))._immutableReferenceMember = immutableReferenceMember;
}
else
throw new Exception(_identifier + new ImmutableType().TypeIdentity + ”> already initialized.“);
}
public static ImmutableRequestSingleton<ImmutableType> Current
{
get
{
if (HttpContext.Current.Items[_identifier + new ImmutableType().TypeIdentity] == null)
return (ImmutableRequestSingleton<ImmutableType>)null; // throw new Exception(”ImmutableRequestSingleton not initialized.”);
else
return (ImmutableRequestSingleton<ImmutableType>)HttpContext.Current.Items[_identifier + new ImmutableType().TypeIdentity];
}
}
// note: readonly modifier is not used, but writing is controlled conditionally within Initialize()
private ImmutableType _immutableReferenceMember;
public ImmutableType ImmutableReferenceMember
{
get { return _immutableReferenceMember; }
}
}
public interface IIdentifiable
{
string TypeIdentity { get; }
}
}
Open in new window. Btw, I’m using Windows Live Writer Beta with the Syntax Highligher plugin (available in a bundle here), though I did have to go through and throw in a bunch of
’s to fix the wrapping in the scrollable div
..
My use for such a pattern is to address cross-cutting security requirements, specifically making consumer credentials available as part of the “background environment” to all objects at all layers of a web service I’m working on, rather than having to pass that information around from adapter to business to resource layers.
As for that gossip and those secrets about myself: just kidding. But here’s an insane video clip and associated music video. Insane insane insane. And how great are the blank stares on the faces of the audience members in the music video?