/// <summary>
        /// Output a given expression tree to a string.
        /// </summary>
        internal static string ExpressionToString(Expression node)
        {
            Debug.Assert(node != null);
            MindboxExpressionStringBuilder esb = new MindboxExpressionStringBuilder();

            esb.Visit(node);
            return(esb.ToString());
        }
        public object Evaluate(Expression expression)
        {
            var cacheKey       = MindboxExpressionStringBuilder.ExpressionToString(expression);
            var cachedDelegate = compiledExpressionsCache.GetOrAdd(cacheKey, key =>
            {
                var arrayOfValuesParameter = Expression.Parameter(typeof(object[]));
                var parametrizedBody       = Parametrize(expression, arrayOfValuesParameter);
                if (parametrizedBody.Type.IsValueType)
                {
                    parametrizedBody = Expression.Convert(parametrizedBody, typeof(object));
                }

                var effectiveQuery = Expression.Lambda <Func <object[], object> >(
                    parametrizedBody,
                    arrayOfValuesParameter
                    );

                return(effectiveQuery.Compile());
            });

            var capturedValues = GetCapturedValues(expression);

            return(cachedDelegate(capturedValues));
        }