public static Expression ReplaceParameters([NotNull] Dictionary <ParameterExpression, Expression> map, [NotNull] Expression exp) { var result = new ExpressionParameterRebinder(map).Visit(exp); return(result ?? exp); }
/// <summary> /// Compose two <c>Expression</c> int one by merge function. /// </summary> /// <typeparam name="TExpression">Type of <c>Expression</c>.</typeparam> /// <param name="left">Base first <c>Expression</c>.</param> /// <param name="right">Base second <c>Expression</c>.</param> /// <param name="merge">Merge function.</param> /// <returns> /// Lambda <c>Expression</c> created with <paramref name="left" />, <paramref name="right" /> <c>Expressions</c> /// and <paramref name="merge" /> function. /// </returns> /// <example> /// <code> /// Expression<Func<string, bool>> baseExp1 = str => string.IsNullOrEmpty(str); /// Expression<Func<string, bool>> baseExp2 = s => s.Length > 0; /// Expression newExp = ExpressionComposer.Compose(baseExp1, baseExp2, Expression.AndAlso); /// // str => string.IsNullOrEmpty(str) AndAlso (str.Length > 0) /// </code> /// </example> /// <exception cref="ArgumentNullException"> /// Thrown when <paramref name="left" />, <paramref name="right" /> /// or <paramref name="merge" /> is null. /// </exception> internal static Expression <TExpression> Compose <TExpression>(Expression <TExpression> left, Expression <TExpression> right, Func <Expression, Expression, Expression> merge) { left = left ?? throw new ArgumentNullException(nameof(left)); right = right ?? throw new ArgumentNullException(nameof(right)); merge = merge ?? throw new ArgumentNullException(nameof(merge)); // build parameter map (from parameters of right to parameters of left) var map = left.Parameters.Select((f, i) => new { f, s = right.Parameters[i] }) .ToDictionary(p => p.s, p => (Expression)p.f); // replace parameters in the right lambda expression with parameters from the left var secondBody = ExpressionParameterRebinder.ReplaceParameters(map, right.Body); // apply composition of lambda expression bodies to parameters from the left expression return(Expression.Lambda <TExpression>(merge(left.Body, secondBody), left.Parameters)); }