Caching API

Caching, like other utility code, can often clutter your nice clean methods. So why not tuck it away behind a user friendly API? With bonus points for a “fluent interface” :)

using System;

namespace Your.Namespace.Here
{
	public interface ICache
	{
		ICacheLifespan<T> Cache<T>(Func<T> factory);
	}

	public interface ICacheLifespan<T>
	{
		ICacheKeying<T> For(TimeSpan timeToLive);
	}

	public interface ICacheKeying<T>
	{
		T WithKey(string cacheKey);
	}

    public class InMemoryCache : ICache
	{
		private readonly ObjectCache _cache;

		public InMemoryCache(ObjectCache cache)
		{
			_cache = cache;
		}

		public ICacheLifespan<T> Cache<T>(Func<T> factory)
		{
			return new CacheLifespan<T>((ttl, k) =>
			{
				if (_cache.Contains(k))
					return (T)_cache[k];

				var value = factory();

				var cacheItemPolicy = new CacheItemPolicy
				{
					AbsoluteExpiration = DateTimeOffset.Now.Add(ttl)
				};
				_cache.Add(k, value, cacheItemPolicy);

				return value;
			});
		}
	}

	public class CacheLifespan<T> : ICacheLifespan<T>
	{
		private readonly Func<TimeSpan, string, T> _factory;

		public CacheLifespan(Func<TimeSpan, string, T> factory)
		{
			_factory = factory;
		}

		public ICacheKeying<T> For(TimeSpan timeToLive)
		{
			return new CacheKeying<T>(timeToLive, _factory);
		}
	}

	public class CacheKeying<T> : ICacheKeying<T>
	{
		private readonly TimeSpan _timeToLive;
		private readonly Func<TimeSpan, string, T> _factory;

		public CacheKeying(TimeSpan timeToLive, Func<TimeSpan, string, T> factory)
		{
			_timeToLive = timeToLive;
			_factory = factory;
		}

		public T WithKey(string cacheKey)
		{
			return _factory(_timeToLive, cacheKey);
		}
	}

	public class Examples
	{
		private readonly InMemoryCache inMemoryCache = new InMemoryCache(new ObjectCache());

		[Test]
		public void Fluent_caching()
		{
			inMemoryCache.Cache(() => CreateExpensiveObject())
				.For(TimeSpan.FromHours(1))
				.WithKey("cacheKey");
		}
	}
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s