Reputation: 462
Masters,
We have implemented CacheManager and SessionManager in past applications by various ways, like by creating a SessionHelper
static class and a CacheHelper
static class.
Though it works fine, we lack some ability for generalization and globalization perspective. So for new scratch development, we intend best practices for such general implementation in terms of flexibility and extensibility.
Please suggest.
Upvotes: 2
Views: 7495
Reputation: 1726
You could create an interface to define the common operations used in Caching and Session management, named something like IStateManager. e.g.
/// <summary>
/// An interface to provide access to a state storage implementation
/// </summary>
public interface IStateManager
{
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value associated with the specified key.</returns>
T Get<T>(string key);
/// <summary>
/// Adds the specified key and object to the state manager.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
void Set(string key, object data);
/// <summary>
/// Adds the specified key and object to the state manager.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
void Set(string key, object data, int cacheTime);
/// <summary>
/// Gets a value indicating whether the value associated with the specified key is in the state manager.
/// </summary>
/// <param name="key">key</param>
/// <returns>Result</returns>
bool IsSet(string key);
/// <summary>
/// Removes the value with the specified key from the state manager.
/// </summary>
/// <param name="key">/key</param>
void Remove(string key);
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
void RemoveByPattern(string pattern);
/// <summary>
/// Clear all state manager data
/// </summary>
void Clear();
}
Then, you could create implementations of the interface to provide different functionality. E.g. an in memory implementation, that uses System.Runtime.Caching
/// <summary>
/// Represents an in memory cache
/// </summary>
public class MemoryCacheManager : IStateManager
{
public MemoryCacheManager()
{
}
protected ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value associated with the specified key.</returns>
public T Get<T>(string key)
{
return (T)Cache[key];
}
/// <summary>
/// Adds the specified key and object to the cache with a default cache time of 30 minutes.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
public void Set(string key, object data)
{
Set(key, data, 30);
}
/// <summary>
/// Adds the specified key and object to the cache.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
public void Set(string key, object data, int cacheTime)
{
if (data == null)
return;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
}
/// <summary>
/// Gets a value indicating whether the value associated with the specified key is cached
/// </summary>
/// <param name="key">key</param>
/// <returns>Result</returns>
public bool IsSet(string key)
{
return (Cache.Contains(key));
}
/// <summary>
/// Removes the value with the specified key from the cache
/// </summary>
/// <param name="key">/key</param>
public void Remove(string key)
{
Cache.Remove(key);
}
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
public void RemoveByPattern(string pattern)
{
var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
var keysToRemove = new List<String>();
foreach (var item in Cache)
if (regex.IsMatch(item.Key))
keysToRemove.Add(item.Key);
foreach (string key in keysToRemove)
{
Remove(key);
}
}
/// <summary>
/// Clear all cache data
/// </summary>
public void Clear()
{
foreach (var item in Cache)
Remove(item.Key);
}
}
You could create multiple implementations of this interface, such as a 'Memcached' implementation to provide distributed caching for your application or a 'Session' implementation to provide user session based functionality.
Then, you can use your dependency container of choice to inject the implementations into your services\controllers and wire up your application.
Try and avoid static classes which can be problematic to unit test.
Upvotes: 10
Reputation: 346
Can use the filter attributes for caching and can handle session through the singleton class..
http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx
you can get some samples in the above link for the best way or approach to be followed.
Upvotes: 0