/// <summary>
        /// Analyses the provided expression and returns a DeferTransformation instance containing
        /// information necessary to defer execution of expressions identified as unsuitable by the
        /// supplied IExpressionAnalyser
        /// </summary>
        /// <param name="expression">The LINQ query expression to be analysed</param>
        /// <param name="analyserFactory">A factory lambda used to retrieve an instance of the desired IExpressionAnalyser</param>
        /// <returns>The results of the transformation process</returns>
        public static DeferTransformation Transform(Expression expression, Func <IExpressionAnalyser> analyserFactory)
        {
            var analyser = analyserFactory();
            var instance = new DeferExpressionTransformer(analyser);

            instance._transformation.TransformedExpression = instance.Visit(expression);

            return(instance._transformation);
        }
        /// <summary>
        /// Wraps and executes the supplied expression.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public IEnumerator <T> ExecuteQuery <T>(Expression expression)
        {
            // transform the expression into the intermediate query, building the transformation
            // object at the same time for postprocessing
            var transformation = DeferExpressionTransformer.Transform(expression, _config.AnalyserFactory);

            // create the inner query, which produces the intermediate objects
            var createQueryMethod = typeof(IQueryProvider).GetGenericMethod("CreateQuery", BindingFlags.Instance | BindingFlags.Public, new[] { transformation.IntermediateItemType }, new[] { typeof(Expression) });
            var intermediateQuery = createQueryMethod.Invoke(_innerProvider, new object[] { transformation.TransformedExpression });

            // get the enumerator for the results of the inner query
            var enumerableType         = typeof(IEnumerable <>).MakeGenericType(transformation.IntermediateItemType);
            var getEnumeratorMethod    = enumerableType.GetMethod("GetEnumerator");
            var intermediateEnumerator = getEnumeratorMethod.Invoke(intermediateQuery, new object[] { });

            // wrap the inner enumerator with our post-processing enumerator and we're done
            var postProcessEnumerator = new DeferPostProcessEnumerator <T>((IEnumerator)intermediateEnumerator, transformation.PostProcessLambda);

            return(postProcessEnumerator);
        }