Posted by: leppie | October 20, 2008

Simple memomization with LINQ

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;

namespace CacheExtensions
{
  static class PersistentCache
  {
    static Dictionary<string, object> cache = new Dictionary<string, object>();

    public static R Call<T,R>(this T p, Expression<Func<T, R>> func)
    {
      string index = GetIndex(func);
      object co;
      if (cache.TryGetValue(index, out co))
      {
        return (R)co;
      }
      else
      {
        Func<T, R> cfunc = func.Compile();
        var cf = cfunc(p);
        cache[index] = cf;
        return cf;
      }
    }

    static string GetIndex<T, R>(Expression<Func<T, R>> func)
    {
      var mc = func.Body as MethodCallExpression;

      var cc = Expression.Lambda(
        Expression.Call(
          makekey,
          Expression.NewArrayInit(typeof(object), mc.Arguments))).Compile()
        as Func<string>;

      return string.Format("{0}({1})", mc.Method.Name, cc());
    }

    readonly static MethodInfo makekey = new Func<object[],string>(MakeKey).Method;

    public static string MakeKey(params object[] args)
    {
      string[] a = Array.ConvertAll(args, o => o == null ? "null" : ( "'" + o + "'" ));
      return string.Join(",", a);
    }
  }
}
Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

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

Categories

%d bloggers like this: