/// <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); }