Created
July 12, 2013 06:46
-
-
Save maximilian-krauss/5982424 to your computer and use it in GitHub Desktop.
Very simple object cache with support for object expiration
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.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Xml.Serialization; | |
namespace kraussHQ { | |
public sealed class BlobCacheEntry { | |
public DateTime ExpireDate { get; set; } | |
public string Key { get; set; } | |
public string Identifier { get; set; } | |
public string FullBlobPath(string storageDirectory) { | |
return Path.Combine(storageDirectory, string.Format("{0}.xml", Identifier)); | |
} | |
} | |
interface IBlobCache { | |
void Add<T>(string key, T value) where T : class; | |
void Add<T>(string key, T value, DateTime expireDate) where T : class; | |
bool KeyExists(string key); | |
void Remove(string key); | |
T Retrieve<T>(string key) where T : class; | |
} | |
public sealed class ShortTermBlobCache : IBlobCache { | |
private const string IndexFileName = "BlobCacheIndex.xml"; | |
private const int DefaultObjectLifetimeInHours = 10; | |
private readonly string _StorageDirectory; | |
private readonly string _IndexPath; | |
private List<BlobCacheEntry> _Index; | |
public ShortTermBlobCache() | |
: this(Path.Combine(Environment.ExpandEnvironmentVariables("%tmp%"), "BlobCache")) { | |
} | |
public ShortTermBlobCache(string storageDirectory) { | |
_StorageDirectory = storageDirectory; | |
if (!Directory.Exists(_StorageDirectory)) | |
Directory.CreateDirectory(_StorageDirectory); | |
_IndexPath = Path.Combine(_StorageDirectory, IndexFileName); | |
if (File.Exists(_IndexPath)) { | |
using (var reader = new StreamReader(_IndexPath, Encoding.UTF8)) { | |
var serializer = new XmlSerializer(typeof(List<BlobCacheEntry>)); | |
_Index = (List<BlobCacheEntry>)serializer.Deserialize(reader); | |
CleanCache(); | |
} | |
} | |
else | |
_Index = new List<BlobCacheEntry>(); | |
} | |
private void SaveIndex() { | |
CleanCache(); | |
using (var writer = new StreamWriter(_IndexPath, false, Encoding.UTF8)) { | |
var serializer = new XmlSerializer(typeof(List<BlobCacheEntry>)); | |
serializer.Serialize(writer, _Index); | |
} | |
} | |
private void CleanCache() { | |
for (var i = _Index.Count - 1; i >= 0; i--) { | |
var blob = _Index[i]; | |
if (blob.ExpireDate > DateTime.MinValue && DateTime.Now > blob.ExpireDate) { | |
_Index.RemoveAt(i); | |
var blobPath = blob.FullBlobPath(_StorageDirectory); | |
if (File.Exists(blobPath)) | |
File.Delete(blobPath); | |
} | |
} | |
} | |
public void Add<T>(string key, T value) where T : class { | |
Add<T>(key, value, DateTime.Now.AddHours(DefaultObjectLifetimeInHours)); | |
} | |
public void Add<T>(string key, T value, DateTime expireDate) where T : class { | |
if (_Index.Any(b => b.Key == key.ToLowerInvariant())) | |
throw new ArgumentException("An item with the same key has already been added."); | |
var blob = new BlobCacheEntry { | |
Key = key.ToLowerInvariant(), | |
Identifier = Guid.NewGuid().ToString(), | |
ExpireDate = expireDate | |
}; | |
using (var writer = new StreamWriter(blob.FullBlobPath(_StorageDirectory), false, Encoding.UTF8)) { | |
var serializer = new XmlSerializer(typeof(T)); | |
serializer.Serialize(writer, value); | |
} | |
_Index.Add(blob); | |
SaveIndex(); | |
} | |
public T Retrieve<T>(string key) where T : class { | |
CleanCache(); | |
SaveIndex(); | |
var blob = _Index.SingleOrDefault(b => b.Key == key.ToLowerInvariant()); | |
if (blob == null) | |
throw new KeyNotFoundException(); | |
using (var reader = new StreamReader(blob.FullBlobPath(_StorageDirectory), Encoding.UTF8)) { | |
var serializer = new XmlSerializer(typeof(T)); | |
return (T)serializer.Deserialize(reader); | |
} | |
} | |
public void Remove(string key) { | |
var blob = _Index.FirstOrDefault(b => b.Key == key.ToLowerInvariant()); | |
if (blob == null) | |
return; | |
_Index.Remove(blob); | |
CleanCache(); | |
SaveIndex(); | |
} | |
public bool KeyExists(string key) { | |
return _Index.Any(b => b.Key == key.ToLowerInvariant()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment