1: public sealed class CachedFunction<T, TResult>
2: {
3: private Func<T, TResult> _function;
4: private int _cacheSize;
5: private Dictionary<T, CacheInformation<T, TResult>> _cache;
6:
7: // The constructor for the CachedFunction class.
8: private CachedFunction(Func<T, TResult> function, int cacheSize)
9: {
10: this._function = function;
11: this._cacheSize = cacheSize;
12: this._cache = new Dictionary<T, CacheInformation<T, TResult>>(this._cacheSize);
13: }
14:
15: // A factory method that created a new instance of the CacheFunction class with the default cache size.
16: public static CachedFunction<T, TResult> Create(Func<T, TResult> function)
17: {
18: return Create(function, 10);
19:
20: }
21:
22: // A factory method that created a new instance of the CacheFunction class.
23: public static CachedFunction<T, TResult> Create(Func<T, TResult> function, int cacheSize)
24: {
25: if (function == null)
26: throw new ArgumentNullException("function");
27: if (cacheSize <= 0)
28: throw new ArgumentOutOfRangeException("cacheSize", Resources.ArgumentOutOfRangeExceptionIntLessThanOneMessage);
29:
30: return new CachedFunction<T,TResult>(function, cacheSize);
31: }
32:
33: // This method is called to execute the function with the argument specified.
34: // If the argument exists in the cache, the cached result is returned, otherwise
35: // the original function is called and the result is added to the cache.
36: public TResult Execute(T arg1)
37: {
38: if (this._cache.ContainsKey(arg1))
39: return this.GetReturnFromCache(arg1);
40: else
41: {
42: TResult returnValue = this._function(arg1);
43: this.AddToCache(arg1, returnValue);
44: return returnValue;
45: }
46: }
47:
48: // This method adds a new argument/result pair to the cache. If the size
49: // if the cache dictionary exceeds the cache size value, then the oldest cached
50: // result with the smallest number of executions is removed from the cache.
51: private void AddToCache(T argument1, TResult returnValue)
52: {
53: if (this._cache.Count >= this._cacheSize)
54: {
55: int min = this._cache.Min(x => x.Value.ExecutionCount);
56: this._cache.Remove(this._cache.First(x => x.Value.ExecutionCount == min).Key);
57: }
58:
59: this._cache.Add(argument1, CacheInformation<T, TResult>.Create(argument1, returnValue));
60: }
61:
62: // This method returns a function result from the cache that corresponds
63: // to the given argument.
64: private TResult GetReturnFromCache(T argument1)
65: {
66: return this._cache[argument1].ReturnValue;
67: }
68: }