protected override Expression ReduceInternal() { var originalItemValue = Expression.Parameter(CurrentItem.Type, "foreachOriginalItem"); var originalIndex = Expression.Parameter(typeof(object), "foreachOriginalVelocityIndex"); //Need to store the enumerable in a local variable so we don't end up computing it twice (once with the TypeAs check, and again with the execution) var localEnumerable = Expression.Parameter(typeof(IEnumerable), "foreachEnumerable"); var body = ((RenderedBlock)Body).Children; var parts = GetParts(body); var forEach = new TemplatedForeachExpression( enumerable: localEnumerable, loopVariable: CurrentItem, loopIndex: CurrentIndex, breakLabel: _break, beforeAll: GetExpressionBlock(parts, ForeachSection.BeforeAll), before: GetExpressionBlock(parts, ForeachSection.Before), odd: GetExpressionBlock(parts, ForeachSection.Odd), even: GetExpressionBlock(parts, ForeachSection.Even), between: GetExpressionBlock(parts, ForeachSection.Between), after: GetExpressionBlock(parts, ForeachSection.After), afterAll: GetExpressionBlock(parts, ForeachSection.AfterAll), each: GetExpressionBlock(parts, ForeachSection.Each), noData: GetExpressionBlock(parts, ForeachSection.NoData) ); var loopExecution = Expression.Block( typeof(void), new[] { originalIndex, originalItemValue }, Expression.Assign(originalItemValue, CurrentItem), Expression.Assign(originalIndex, CurrentIndex), forEach, Expression.Assign(CurrentIndex, originalIndex), Expression.Assign(CurrentItem, originalItemValue) ); return(new TemporaryVariableScopeExpression( localEnumerable, Expression.Block( Expression.Assign(localEnumerable, Expression.TypeAs(Enumerable, typeof(IEnumerable))), Expression.IfThenElse( Expression.Equal(localEnumerable, _nullEnumerable), forEach.NoData ?? Constants.EmptyExpression, loopExecution ) ) )); }
protected virtual Expression VisitTemplatedForEach(TemplatedForeachExpression node) => base.VisitExtension(node);