/// <summary>
        /// Visits a <see cref="WhereOperator" /> and coalesces it with any possible child operators.
        /// </summary>
        /// <param name="op">The operator to visit.</param>
        /// <returns>The coalesced operator.</returns>
        protected internal override QueryOperator VisitWhere(WhereOperator op)
        {
            var source    = VisitAndConvert <MonadMember>(op.Source);
            var predicate = Visit(op.Predicate);

            var srcOperator = source.QueryNodeType == QueryNodeType.Operator ? (QueryOperator)source : null;
            var srcWhere    = srcOperator != null && srcOperator.NodeType == OperatorType.Where ? (WhereOperator)srcOperator : null;

            if (srcWhere != null && op.ElementType == srcWhere.ElementType)
            {
                var p = Expression.Parameter(op.ElementType);
                if (TryExtractNullaryLambdaBody(srcWhere.Predicate, out Expression predicate1) && TryExtractNullaryLambdaBody(predicate, out Expression predicate2))
                {
                    var reduced1 = BetaReducer.Reduce(Expression.Invoke(predicate1, p));
                    var reduced2 = BetaReducer.Reduce(Expression.Invoke(predicate2, p));

                    return(op.QueryExpressionFactory.Where(
                               op.ElementType,
                               srcWhere.Source,
                               DefaultQueryExpressionFactory.Instance.LambdaAbstraction(
                                   Expression.Lambda(
                                       Expression.Lambda(
                                           Expression.AndAlso(reduced1, reduced2),
                                           p
                                           )
                                       ),
                                   Array.Empty <QueryTree>()
                                   )
                               ));
                }

                var predicateType = typeof(Func <,>).MakeGenericType(p.Type, typeof(bool));
                var p1            = Expression.Parameter(predicateType);
                var p2            = Expression.Parameter(predicateType);
                return(op.QueryExpressionFactory.Where(
                           op.ElementType,
                           srcWhere.Source,
                           DefaultQueryExpressionFactory.Instance.LambdaAbstraction(
                               Expression.Lambda(
                                   Expression.Lambda(
                                       Expression.AndAlso(
                                           Expression.Invoke(p1, p),
                                           Expression.Invoke(p2, p)
                                           ),
                                       p
                                       ),
                                   p1,
                                   p2
                                   ),
                               new[] { srcWhere.Predicate, predicate }
                               )
                           ));
            }

            return(op.Update(source, predicate));
        }
示例#2
0
        /// <summary>
        /// Visits a <see cref="WhereOperator" /> node.
        /// </summary>
        /// <param name="op">Node to visit.</param>
        /// <returns>Result of visiting the node.</returns>
        protected internal override QueryOperator VisitWhere(WhereOperator op)
        {
            var src  = VisitAndConvert <MonadMember>(op.Source);
            var pred = Visit(op.Predicate);

            if (src != op.Source || pred != op.Predicate)
            {
                return(MakeWhere(op, src, pred));
            }

            return(op);
        }
示例#3
0
 /// <summary>
 /// Makes a <see cref="WhereOperator" /> with the given children.
 /// </summary>
 /// <param name="node">Original query expression.</param>
 /// <param name="source">Source query expression.</param>
 /// <param name="predicate">Predicate query expression.</param>
 /// <returns>Representation of the original query expression.</returns>
 protected sealed override QueryOperator MakeWhere(WhereOperator node, MonadMember source, QueryTree predicate)
 {
     return(node.QueryExpressionFactory.Where(node.ElementType, source, predicate));
 }
示例#4
0
 /// <summary>
 /// Creates a textual representation of the WhereOperator with the given children.
 /// </summary>
 /// <param name="node">Original query expression.</param>
 /// <param name="source">Source query expression.</param>
 /// <param name="predicate">Predicate query expression.</param>
 /// <returns>Representation of the original query expression.</returns>
 protected override string MakeWhere(WhereOperator node, string source, string predicate)
 {
     return(string.Format(CultureInfo.InvariantCulture, "@Where({0}, {1})", source, predicate));
 }
示例#5
0
 /// <summary>
 /// Makes a <see cref="WhereOperator" /> with the given children.
 /// </summary>
 /// <param name="node">Original query expression.</param>
 /// <param name="source">Source query expression.</param>
 /// <param name="elementType">Element type for the resulting operator.</param>
 /// <param name="predicate">Predicate query expression.</param>
 /// <returns>Representation of the original query expression.</returns>
 protected virtual QueryOperator MakeWhere(WhereOperator node, Type elementType, MonadMember source, QueryTree predicate)
 {
     return(node.QueryExpressionFactory.Where(elementType, source, predicate));
 }