Last active
August 25, 2016 20:46
-
-
Save Feasoron/d10611fa2001527135d2 to your computer and use it in GitHub Desktop.
Self-Caching Object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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