I recently had to write a lazy loaded property that picked what its value will be based on the environment it run on. Basically, I had the same old problem of keeping data for the current context only. This usually means the current thread, but in ASP.Net, it is the current request.
My solution for it was simple:
.
So I can store/retrieve data without caring in what environment I’m running on by simply using:
CurrentData.Items["current-db-connection"] = new SqlConnection();
I need this ability to store data that is important for the current logical execution thread (be that an ASP.Net request or a real thread). The usual method of implemention the Items property on the CurrentData class would be something like:
public static ICurrentDataStore Items
{
get
{
if (items == null)
items = CreateCurrentDataStoreForEnviornment();
return items;
}
}
But I thought that I could get rid of the null check, this should allow the JIT to view the property as a simple accessor, so it would be just as fast as accessing a field directly. I could’ve simply instasitated the items field to the proper value based on the environment, but I wanted to mimic a real lazy loaded property. I ended up with this class:
public class DataStoreSwitcher : ICurrentDataStore
{
private Action<ICurrentDataStore> set;
public DataStoreSwitcher(Action<ICurrentDataStore> set)
{
this.set = set;
}
#region ICurrentDataStore Members
public object this[object key]
{
get
{
ICurrentDataStore real = EnsureCorrectDataStoreForEnvironment();
return real[key];
}
set
{
ICurrentDataStore real = EnsureCorrectDataStoreForEnvironment();
real[key] = value;
}
}
private ICurrentDataStore EnsureCorrectDataStoreForEnvironment()
{
ICurrentDataStore real;
if (HttpContext.Current == null)
real = new CurrentThreadDataStore();
else
real = new CurrentRequestDataStore();
set(real);
return real;
}
#endregion
}
I initialize the variable like this:
private static ICurrentDataStore items =
new DataStoreSwitcher(
delegate(ICurrentDataStore real)
{
items = real;
});
In this particular point, there is very little to be gain from this technqiue, and if the case was a hefty resource (choosing database connection, for instance), it can certainly be useful. Beside, I like using delegate J, and it’s a cool thing to do.