Caching compiled lambda expressions

I need to get some information passed as a lambda expression to some methods. Basically, this is a way to add information to a database query. A simple example:

companyData.GetAll(
   where => "SomeField = @SOMEFIELD",
   order => "Id",
   SOMEFIELD => new Parameter {DbType = DbType.String, Value = "some value"}
)

It works very well, except for the fact that I need to call LambdaExpression.Compile to get a parameter object that has a big impact.

To get faster results, I came up with this naive caching test:

class ExpressionCache<T,U>
{

    private static ExpressionCache<T, U> instance;
    public static ExpressionCache<T, U> Instance
    {
        get
        {
            if (instance == null) {
                instance = new ExpressionCache<T, U>();
            }
            return instance;
        }
    }

    private ExpressionCache() { }

    private Dictionary<string, Func<T, U>> cache = new Dictionary<string, Func<T, U>>();

    public Func<T, U> Get(Expression<Func<T, U>> expression)
    {
        string key = expression.Body.ToString();
        Func<T,U> func;
        if (cache.TryGetValue(key, out func)) {
            return func;
        }
        func = expression.Compile();
        cache.Add(key, func);
        return func;
    }
}

This class made a huge contribution: from about 35,000 milliseconds in 10,000 iterations to about 700.

Now the question is: what problem will I use as an expression for the dictionary?

+3
2

, , . - ?

- , , . , , , , , ... , , .

, singleton . , instance . , , ...

private static readonly ExpressionCache<T, U> instance
     = new ExpressionCache<T, U>();
public static ExpressionCache<T, U> Instance { get { return instance; } }
+9

- . , , . , , .

+9

Source: https://habr.com/ru/post/1718311/


All Articles