ILearnable .Net

May 19, 2008

Generic cache method

Filed under: Uncategorized — andreakn @ 06:44

All of our code interacting with the cache is on the form

string key = “persons”
var cache = SimpleCache.Instance;
if(cache.Exists(key) && !HasExpired(Key)
{
return cache.Get(key);
}
else
{
int timeout_in_minutes = 5;
var persons = PersonDAO.GetAllPersons();
cache.Add(persons, timeout_in_minutes)
return persons;
}

So it’s pretty tedious code to write, but relatively short and sweet. somewhat easy to introduce errors in the cache logic (which really should be the cache’s responsibility after all)

I decided I would try to write one that would be easier to consume, and here is code
showing what I ended up with. The tests run as expected, I will leave it up to the reader
(if I indeed have any) to figure out how CacheFetch gets stuff done, I found it to be pretty
(yet a bit hard to grok) code that exemplifies the use of lambda-expressions and how a lambda
can access variables that were present where it was defined, in addition to those present (in the form of input params) where it is executed

<!–
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf1 using\cf0 System.Threading;\par ??\cf1 using\cf0 NUnit.Framework;\par ??\par ??\cf1 namespace\cf0 Business.Test\par ??\{\par ?? [\cf4 TestFixture\cf0 ]\par ?? \cf1 public\cf0 \cf1 class\cf0 \cf4 TestLambdas\par ??\cf0 \{\par ?? [\cf4 Test\cf0 ]\par ?? \cf1 public\cf0 \cf1 void\cf0 TestLamda()\par ?? \{\par ?? \cf1 var\cf0 serv = \cf1 new\cf0 \cf4 Serv\cf0 ();\par ?? \cf1 var\cf0 s1 = serv.GetCurrentMillis();\par ?? \cf4 Thread\cf0 .Sleep(20);\par ?? \cf1 var\cf0 s2 = serv.GetCurrentMillis();\par ?? \cf4 Assert\cf0 .AreEqual(s1, s2);\par ?? \}\par ??\par ?? [\cf4 Test\cf0 ]\par ?? \cf1 public\cf0 \cf1 void\cf0 TestLamda2()\par ?? \{\par ?? \cf1 var\cf0 serv = \cf1 new\cf0 \cf4 Serv\cf0 ();\par ?? \cf1 var\cf0 s1 = serv.GetRandomString(10);\par ?? \cf4 Thread\cf0 .Sleep(20);\par ?? \cf1 var\cf0 s2 = serv.GetRandomString(10);\par ?? \cf4 Assert\cf0 .AreEqual(s1, s2);\par ?? \cf4 Thread\cf0 .Sleep(20);\par ?? \cf1 var\cf0 s3 = serv.GetRandomString(10);\par ?? \cf4 Assert\cf0 .AreEqual(s2, s3);\par ?? \}\par ?? \}\par ??\par ?? \cf1 public\cf0 \cf1 class\cf0 \cf4 Serv\par ??\cf0 \{ \par ?? \cf1 public\cf0 \cf1 string\cf0 GetRandomString(\cf1 int\cf0 max_rand)\par ?? \{\par ?? \cf1 return\cf0 CacheFetch(\cf5 “rand”\cf0 , () => \cf5 “rand”\cf0 +\cf1 new\cf0 \cf4 Random\cf0 ().Next(max_rand) ,5);\par ?? \}\par ?? \cf1 public\cf0 \cf1 int\cf0 GetCurrentMillis()\par ?? \{\par ?? \cf1 return\cf0 CacheFetch(\cf5 “day”\cf0 , () => \cf4 DateTime\cf0 .Now.Millisecond, 5);\par ?? \}\par ??\par ?? \cf1 public\cf0 \cf1 delegate\cf0 T \cf4 Fetch\cf0 ();\par ??\par ?? \cf1 public\cf0 T CacheFetch(K key, \cf4 Fetch\cf0 fetcher, \cf1 int\cf0 cacheMinutes)\par ?? \{\par ?? \cf1 var\cf0 cache = \cf4 SimpleCache\cf0 .Instance;\par ?? \cf1 if\cf0 (cache.Exists(key) && !cache.HasExpired(key))\par ?? \{\par ?? \cf1 return\cf0 cache.GetItem(key);\par ?? \}\par ?? \cf1 var\cf0 retVal = fetcher();\par ?? cache.AddItem(key, retVal, cacheMinutes);\par ?? \cf1 return\cf0 retVal;\par ?? \}\par ?? \}\par ??\}}
–>

using System.Threading;

using NUnit.Framework;

 

namespace Business.Test

{

    [TestFixture]

    public class TestLambdas

    {

        [Test]

        public void TestLamda()

        {

            var serv = new Serv();

            var s1 = serv.GetCurrentMillis();

            Thread.Sleep(20);

            var s2 = serv.GetCurrentMillis();

            Assert.AreEqual(s1, s2);

        }

 

        [Test]

        public void TestLamda2()

        {

            var serv = new Serv();

            var s1 = serv.GetRandomString(10);

            Thread.Sleep(20);

            var s2 = serv.GetRandomString(10);

            Assert.AreEqual(s1, s2);

            Thread.Sleep(20);

            var s3 = serv.GetRandomString(10);

            Assert.AreEqual(s2, s3);

        }

    }

 

    public  class Serv

    {

        public string GetRandomString(int max_rand)

        {

         
   return CacheFetch(“rand”, () => “rand”+new Random().Next(max_rand) ,5);

        }

        public int GetCurrentMillis()

        {

            return CacheFetch(“day”, () => DateTime.Now.Millisecond, 5);

        }

 

        public delegate T Fetch();

 

        public T CacheFetch(K key, Fetch fetcher, int cacheMinutes)

        {

            var cache = SimpleCache.Instance;

            if (cache.Exists(key) && !cache.HasExpired(key))

            {

               return cache.GetItem(key);

            }

            var retVal = fetcher();

            cache.AddItem(key, retVal, cacheMinutes);

            return retVal;

        }

    }

}

Blog at WordPress.com.