Skip to content

Instantly share code, notes, and snippets.

@Feasoron
Last active August 25, 2016 20:46
Show Gist options
  • Save Feasoron/d10611fa2001527135d2 to your computer and use it in GitHub Desktop.
Save Feasoron/d10611fa2001527135d2 to your computer and use it in GitHub Desktop.
Self-Caching Object
using System;
using System.Configuration;
using AutoMapper;
namespace Caching
{
// ReSharper disable DoNotCallOverridableMethodsInConstructor
// In general, calling a pure virtual from a base class can be a problem because it calls the most derived type
// which theoretically could be expecting settings from a constructor that has not been run. For the purposes of
// this class, we are using the load method to define what happens on a cache miss and *need* to call the most
// derived type. Any issues with this will therefore be implementation bugs in the derived class, not an error
// in this base.
public abstract class CacheableObject
{
private readonly ICacheProvider _cache = CacheProviderFactory.GetDefaultProvider();
private readonly ILog _log = LogFactory.GetLog(typeof(CacheableObject));
public abstract void Load();
public object Key;
public Type ObjectType;
public String KeyPrefix { get; set; }
private TimeSpan? _expiry;
public TimeSpan? Expiry
{
set
{
_expiry = value;
}
get
{
if (_expiry.HasValue || String.IsNullOrEmpty(ConfigurationManager.AppSettings["DefaultExpiry"]))
{
return _expiry;
}
return TimeSpan.Parse(ConfigurationManager.AppSettings["DefaultExpiry"]);
}
}
static CacheableObject()
{
Mapper.CreateMap<CacheableObject, CacheableObject>();
}
protected CacheableObject()
{
}
protected CacheableObject(object key, TimeSpan expiry)
:this(key, true)
{
Expiry = expiry;
}
protected CacheableObject(object key, Boolean skipCache = false)
{
Key = key;
ObjectType = GetType();
object cachedString = null;
if (!skipCache)
{
cachedString = _cache.Get(KeyPrefix + Key);
}
if (cachedString == null)
{
Load();
UpdateCache();
}
else
{
Clone(cachedString);
}
}
private void CreateCloneMapping()
{
Mapper.CreateMap(ObjectType, ObjectType);
}
protected virtual void Clone(object objectToClone)
{
CreateCloneMapping();
Mapper.Map(objectToClone, this, ObjectType, ObjectType);
}
public void UpdateCache()
{
try
{
_cache.Store(KeyPrefix + Key, this, Expiry);
}
catch (Exception ex)
{
_log.Error(ex);
}
}
public void Invalidate()
{
_cache.Invalidate(KeyPrefix + Key);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment