ASP Session
Here's two simple functions with generics. The first one allows value types, the second is for objects.
using System;
using System.Web;
/// <summary>
/// Strongly typed access to asp session
/// </summary>
public static class SessionManager
{
/// <summary>
/// Gets the value or default of an object (eg Cache, Session, ViewState)
/// </summary>
/// <typeparam name="T">The expected type</typeparam>
/// <param name="o">The object</param>
/// <returns></returns>
private static T GetValueOrDefault<T>(object o)
{
if (o != null && o is T) return (T)o; //value if exists
return default(T); //default
}
/// <summary>
/// Gets the session value or default (generic version- just pass in the key string and specify the type)
/// </summary>
/// <typeparam name="T">The expected type</typeparam>
/// <param name="key">The session key</param>
/// <returns></returns>
public static T GetSessionValueOrDefault<T>(string key)
{
object o = HttpContext.Current.Session[key];
return GetValueOrDefault<T>(o); //default
}
/// <summary>
/// Gets or sets the user birthday (example). Try to keep all session access behind strongly typed properties of SessionManager like this.
/// </summary>
/// <value>The user birthday.</value>
public static DateTime UserBirthday
{
get
{
return GetValueOrDefault<DateTime>(HttpContext.Current.Session["UserBirthday"]);
}
set { HttpContext.Current.Session.Add("UserBirthday", value); }
}
}
Caching Objects
This is for caching objects (not value types) in a simple generic pattern.
This version is .Net 2.0 and is easily changed to 3.5 (Func<T> is already defined, and the delegate becomes shorter).
//FOR 2.0 ONLY. in 3.5 this is in System.Core
public delegate TResult Func<TResult>();
/// <summary>
/// Generic storage in cache (essentially a wrapper around your data access function)
/// </summary>
public static T LoadCache<T>(string key, Func<T> func) where T : class
{
Cache Cache = HttpRuntime.Cache;
T result = Cache[key] as T;
if (result == null)
{
result = func();
Cache[key] = result;
}
return result;
}
public static IList<Customer> GetCustomers()
{
//3.5
//return Load("GetCustomers", () => DataBroker.GetCustomers());
//2.0
return LoadCache<IList<Customer>>("GetCustomers" + year,
delegate()
{
return DataBroker.GetCustomers();
});
}
In practice, pages talk to "cachable data broker" class in AppCode which is a facade over the actual data broker/data access and caches only when useful.