internal static Expression <Func <T, bool> > AndAlso <T>(this Expression <Func <T, bool> > exp1, Expression <Func <T, bool> > exp2)
        {
            if (exp1 == null)
            {
                return(exp2);
            }

            var parameter = Expression.Parameter(typeof(T));

            var leftVisitor = new ReplaceVisitor(exp1.Parameters[0], parameter);
            var left        = leftVisitor.Visit(exp1.Body);

            var rightVisitor = new ReplaceVisitor(exp2.Parameters[0], parameter);
            var right        = rightVisitor.Visit(exp2.Body);

            return(Expression.Lambda <Func <T, bool> >(
                       Expression.AndAlso(left, right), parameter));
        }
        /// <summary>
        /// Correlates all of the elements of an outer sequence with any matching elements of an inner sequence, based on matching keys.
        /// </summary>
        /// <typeparam name="TOuter">The type of the elements of the outer sequence.</typeparam>
        /// <typeparam name="TInner">The type of the elements of the inner sequence.</typeparam>
        /// <typeparam name="TKey">The type of the keys returned by the key selector functions.</typeparam>
        /// <typeparam name="TResult">The type of the result elements.</typeparam>
        /// <param name="outer">The outer sequence to join.</param>
        /// <param name="inner">The inner sequence to join.</param>
        /// <param name="outerKeySelector">A function to extract the join key from each element of the outer sequence.</param>
        /// <param name="innerKeySelector">A function to extract the join key from each element of the inner sequence.</param>
        /// <param name="resultSelector">A function to create a result element from two matching elements.</param>
        /// <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that has elements of type <typeparamref name="TResult" /> that are obtained by performing an outer join on the input sequences.</returns>
        /// <remarks><para>All elements of <paramref name="outer" /> will be selected, even if there is no matching element in <paramref name="inner" />; in that case, the value that is passed as the second parameter to <paramref name="resultSelector" /> will be the default value for <typeparamref name="TInner" />.</para></remarks>
        public static IQueryable <TResult> LeftJoin <TOuter, TInner, TKey, TResult>(this IQueryable <TOuter> outer, IEnumerable <TInner> inner, Expression <Func <TOuter, TKey> > outerKeySelector, Expression <Func <TInner, TKey> > innerKeySelector, Expression <Func <TOuter, TInner, TResult> > resultSelector)
        {
            if (outer == null)
            {
                throw new ArgumentNullException(nameof(outer));
            }
            if (inner == null)
            {
                throw new ArgumentNullException(nameof(inner));
            }
            if (outerKeySelector == null)
            {
                throw new ArgumentNullException(nameof(outerKeySelector));
            }
            if (innerKeySelector == null)
            {
                throw new ArgumentNullException(nameof(innerKeySelector));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }
            // TODO: this
            var outerExample = new
            {
                o = default(TOuter),
                i = (IEnumerable <TInner>)null
            };
            var type       = outerExample.GetType();
            var expression = Expression.Parameter(type, "a");

            return(outer
                   .GroupJoin(inner, outerKeySelector, innerKeySelector, (o, i) => new { o, i })
                   .SelectMany(
                       x => x.i.DefaultIfEmpty(),
                       Lambda(
                           outerExample,
                           default(TInner),
                           default(TResult),
                           ReplaceVisitor.Replace(resultSelector.Body, resultSelector.Parameters[0], Expression.Property(expression, type.GetProperty("o"))),
                           new[] { expression, resultSelector.Parameters[1] }
                           )
                       ));
        }
        public static Expression <Func <T, bool> > CombineAnd <T>(this IEnumerable <Expression <Func <T, bool> > > filters)
        {
            if (!filters.Any())
            {
                Expression <Func <T, bool> > alwaysTrue = x => true;
                return(alwaysTrue);
            }
            var firstFilter = filters.First();

            var lastFilter = firstFilter;
            Expression <Func <T, bool> > result = null;

            foreach (var nextFilter in filters.Skip(1))
            {
                var nextExpression = new ReplaceVisitor(lastFilter.Parameters[0], nextFilter.Parameters[0]).Visit(lastFilter.Body);
                result     = Expression.Lambda <Func <T, bool> >(Expression.AndAlso(nextExpression, nextFilter.Body), nextFilter.Parameters);
                lastFilter = nextFilter;
            }
            return(result);
        }
        public Expression Join(Expression beforeExpression)
        {
            if (_argumentIndex == -1)
            {
                throw new InvalidOperationException("cannot join not splitted expression");
            }

            var arguments = new Expression[_afterExpression.Arguments.Count];

            for (int i = 0; i < arguments.Length; i++)
            {
                arguments[i] = _afterExpression.Arguments[i];
            }
            arguments[_argumentIndex] = beforeExpression;

            MethodCallExpression newAfterExpression = Expression.Call(_afterExpression.Object, _afterExpression.Method, arguments);
            var visitor = new ReplaceVisitor(_afterExpression, newAfterExpression);

            return(visitor.Visit(_source));
        }
        public void TestDecrement_Subtract1From1_MustReplaceWithDecrement()
        {
            Expression <Func <int, int> > sourceExpression = i => ((i - 2) + (i - 1)) + ((1 + i) - 1);
            var expectedExpression = Expression.Lambda(typeof(Func <int, int>),
                                                       Expression.Add(
                                                           Expression.Add(
                                                               Expression.Subtract(_intParameter, Expression.Constant(2)),
                                                               Expression.Decrement(_intParameter)
                                                               ),
                                                           Expression.Decrement(
                                                               Expression.Increment(_intParameter)
                                                               )
                                                           ),
                                                       _intParameter);

            var actualExpression = new ReplaceVisitor().VisitAndConvert(sourceExpression, string.Empty);

            Assert.NotEqual(sourceExpression.ToString(), actualExpression.ToString()); //replace with real comparison
            Assert.Equal(expectedExpression.ToString(), actualExpression.ToString());  //replace with real comparison
            AssertExpressionsResults((Func <int, int>)expectedExpression.Compile(), (Func <int, int>)actualExpression.Compile(), testParameters);
        }
示例#6
0
        /// <summary>
        /// Remplaza todas las referencias a un elemento del WITH con un SqlTableRefRaw
        /// </summary>
        public static Expression SubqueryRawSubs(Expression subquery, ParameterExpression repParam)
        {
            if (subquery == null)
            {
                return(null);
            }

            //Sustituir todo param.X o param por el nombre:
            var ret = ReplaceVisitor.Replace(subquery, expr =>
            {
                if (typeof(IFromListItemTarget).GetTypeInfo().IsAssignableFrom(expr.Type.GetTypeInfo()))
                {
                    var selectInt = expr.Type.GetTypeInfo().ImplementedInterfaces.Concat(new[] { expr.Type }).Where(x => x.GetTypeInfo().IsGenericType&& x.GetGenericTypeDefinition() == typeof(IFromListItemTarget <>)).FirstOrDefault();
                    if (selectInt == null)
                    {
                        throw new ArgumentException("Debe de ser un IFromListItemTarget<T>");
                    }

                    var selectType = selectInt.GetTypeInfo().GenericTypeArguments[0];

                    if (expr is MemberExpression mem && CompareExpr.ExprEquals(mem.Expression, repParam))
                    {
                        return(RawSqlTableRefExpr(selectType, $"\"{mem.Member.Name}\""));
                    }
        protected static Expression <Func <T, bool> > Combine <T>(Expression <Func <T, bool> > filter1,
                                                                  Expression <Func <T, bool> > filter2)
        {
            if (filter1 == null && filter2 == null)
            {
                return(null);
            }
            if (filter1 == null)
            {
                return(filter2);
            }
            if (filter2 == null)
            {
                return(filter1);
            }

            // combine two predicates:
            // need to rewrite one of the lambdas, swapping in the parameter from the other
            var rewrittenBody1 = new ReplaceVisitor(filter1.Parameters[0],
                                                    filter2.Parameters[0]).Visit(filter1.Body);
            var newFilter = Expression.Lambda <Func <T, bool> >(Expression.AndAlso(rewrittenBody1, filter2.Body), filter2.Parameters);

            return(newFilter);
        }
示例#8
0
        public static IQueryable <T> InlineMatch <T>(this IQueryable <T> e)
        {
            var visitor = new ReplaceVisitor();

            return(e.Provider.CreateQuery <T>(visitor.Visit(e.Expression)));
        }
示例#9
0
        public static T InlineMatch <T>(this T e) where T : Expression
        {
            var visitor = new ReplaceVisitor();

            return((T)visitor.Visit(e));
        }
示例#10
0
        /// <summary>
        /// Devuelve el resultado de aplicar una regla al niver superior de la expresión o la expresión original si la regla no se pudo aplicar a la expresión
        /// </summary>
        public static Expression GlobalApplyRule(Expression expr, RewriteRule rule, Func <Expression, Expression> visit)
        {
            if (rule.DebugName == "convertFromParam" || rule.DebugName == "fromParam")
            {
                ;
            }
            var          parameters = rule.Find.Parameters;
            var          pattBody   = rule.Find.Body;
            PartialMatch partialMatch;

            try
            {
                partialMatch = GlobalMatch(expr, parameters, pattBody);
            }
            catch (Exception ex)
            {
                throw new ApplyRuleException("Error al obtener el match", rule.DebugName, expr, ex);
            }
            var match = PartialMatch.ToFullMatch(partialMatch, parameters);

            if (match == null)
            {
                return(expr);
            }

            if (rule.Condition != null && !rule.Condition(match, expr))
            {
                return(expr);
            }

            //Sustituir la expresión:
            var ret           = expr;
            var replaceLambda = rule.Replace;

            if (replaceLambda != null)
            {
                var subDic = replaceLambda.Parameters
                             .Select((x, i) => (par: x, value: match.Args[i]))
                             .ToDictionary(x => (Expression)x.par, x => x.value)
                ;

                Expression repRet;
                try
                {
                    repRet = ReplaceVisitor.Replace(replaceLambda.Body, subDic, match.Types, x => false);
                }
                catch (Exception ex)
                {
                    throw new ApplyRuleException("Error al reemplazar", rule.DebugName, expr, ex);
                }

                ret = repRet;
            }

            //Aplicar los transforms:
            {
                Expression nextRet;

                try
                {
                    nextRet = ReplaceVisitor.Replace(ret, ex =>
                    {
                        if (ex is MethodCallExpression call && call.Method.DeclaringType == typeof(RewriteSpecial) && call.Method.Name == nameof(RewriteSpecial.Transform))
                        {
                            //Aplica el transform a la expresión:
                            var arg     = call.Arguments[0];
                            var func    = ExprEval.EvalExpr <Func <Expression, Expression> >(call.Arguments[1]);
                            var tResult = func.Value(arg);
                            return(tResult);
                        }
                        return(ex);
                    });
                }
示例#11
0
        static IReadOnlyList<ExprAliasList> ExtractJoinAliasT(IFromListItem left, Expression leftParam, Expression rightParam, Expression onParam, Expression mapExprBody)
        {
            if (left == null)
            {
                return new[] { new ExprAliasList(new ExprRep[0], leftParam, onParam, null) };
            }

            var subRet = ExtractJoinAliasTree(left);
            var leftOnParam = subRet[0].CurrParam;

            var currAliases = mapExprBody == null ? new ExpressionAlias[0] : ExtractAliases(mapExprBody);
            var ret = new List<ExprAliasList>();

            //Si el left no tiene OnParam, debe de existir el lado izquierdo en el mapeo
            var existirLeft = leftOnParam == null;
            if (existirLeft && !currAliases.Any(x => x.Expr == leftParam))
            {
                throw new ArgumentException($"El argumento '{leftParam}' debe de existir en el mapeo del ON del JOIN '{mapExprBody}' ya que el lado izquierdo es un from list que no esta nombrado");
            }

            var mapAliases = currAliases.Select(x => new ExprRep(

                         find: Expression.Property(onParam, x.Alias),
                         rep: Expression.Property(onParam, x.Alias)
                     ))
                     .ToList();

            //Encontrar el alias del left:
            var rightAlias = currAliases.Where(x => x.Expr == rightParam).Select(x => new ExprRep(x.Expr, Expression.Property(onParam, x.Alias))).FirstOrDefault();
            if (rightAlias != null)
            {
                mapAliases.Add(rightAlias);
            }

            var currentExprAlias = new ExprAliasList(mapAliases, leftParam, onParam, null);
            ret.Add(currentExprAlias);

            var repList = currAliases.Select(x => new ExprRep(
                    find: leftOnParam == null ? x.Expr : ReplaceVisitor.Replace(x.Expr, leftParam, leftOnParam),
                    rep: Expression.Property(onParam, x.Alias)
                    ))
                    .ToList();

            //Sustituir todos los subRet:
            var subRetSubs = subRet.Select(list =>
            new ExprAliasList(
                items: list.Items.Select(item => new ExprRep(
                    item.Find,
                    ReplaceExprList(item.Rep, repList)

                    )).ToList(),
                leftParam: list.LeftParam,
                currParam: list.CurrParam,
                leftOn: null
                ))
                .ToList()
                ;
            ret.AddRange(subRetSubs);
            //Agregar el alias del lado izquierdo:
            var leftAlias = currAliases.Where(x => x.Expr == leftParam).Select(x => new ExprRep(x.Expr, Expression.Property(onParam, x.Alias))).FirstOrDefault();
            if (leftAlias != null)
            {
                var fromAlias = new ExprAliasList(new[] { leftAlias }, leftParam, onParam, null);
                ret.Add(fromAlias);
            }
            else
            {
                //Reemplazar el lado izquierdo de este JOIN con el ON del JOIN izquierdo
                leftAlias = new ExprRep(leftParam, leftOnParam);
                var mapAlRep = currAliases.Select(x => new ExprRep(x.Expr, ReplaceVisitor.Replace(x.Expr, leftParam, leftOnParam))).ToList();
                var fromAlias = new ExprAliasList(mapAlRep, leftParam, onParam, null);
                ret.Add(fromAlias);
            }

            return ret;
        }
示例#12
0
        /// <summary>
        /// Applies an expression as argument to a lambda.
        /// </summary>
        /// <param name="lambda">A lambda expression with 1 parameter</param>
        /// <param name="ex">The expression to use as input for the lambda expression</param>
        /// <returns>The expanded body of the LambdaExpression.</returns>
        public static Expression ApplyTo(this LambdaExpression lambda, Expression ex)
        {
            var visitor = new ReplaceVisitor(lambda.Parameters[0], ex);

            return(visitor.Visit(lambda.Body));
        }