src/NetStandard/Linq/Expressions/Expressions/src/SourceTargetExpressionTools.cs
/// <summary>
/// Reduces parameter list by replacing the expression parameter expression
/// usages (of type <typeparamref name="T2"/>) with constant 
/// expression crafted from <paramref name="constant"/>.
/// </summary>
/// <param name="constant">The value that will be used as constant.</param>
/// <param name="lambdaWithParameters">
/// The lambda expression from which the body will be rewritten.
/// </param>
/// <param name="positionalParameterReplacements">
/// Positional parameters that replace parameters before they may get replaced by
/// constants. 
/// (E.g. replace parameter at index two of lambda parameters with specified parameter)
/// </param>
/// <returns>The body that got rewritten.</returns>
Reduces parameter list by replacing the expression parameter expression
usages (of type ) with constant
expression crafted from .
Reduces parameter list by replacing the expression parameter expression usages ( of type ) with constant expression crafted from .
public static Expression ReplaceParameterByConstantLambdaBody(
            LambdaExpression lambdaWithParameters,
            IReadOnlyDictionary<int, ParameterExpression>? positionalParameterReplacements,
            IReadOnlyDictionary<int, object?> positionalConstants,
            out IReadOnlyList<ParameterExpression> positionalParameters)
        {
            lambdaWithParameters = lambdaWithParameters ?? throw new ArgumentNullException(nameof(lambdaWithParameters));
            positionalConstants = positionalConstants ?? throw new ArgumentNullException(nameof(positionalConstants));
            var lambdaParameters = new List<ParameterExpression>(lambdaWithParameters.Parameters);
            Expression visitedLambdaBody;
            if (!(positionalParameterReplacements is null)) {
                var sourceTargetPairs = new SourceTargetPair<ParameterExpression, ParameterExpression>[positionalParameterReplacements.Count];
                var positionalParameterReplacementsEnumerator = positionalParameterReplacements.GetEnumerator();
                var sourceTargetPairsIndex = 0;
                while (positionalParameterReplacementsEnumerator.MoveNext()) {
                    var positionalParameterReplacementEnumeratorCurrent = positionalParameterReplacementsEnumerator.Current;
                    sourceTargetPairs[sourceTargetPairsIndex] = new SourceTargetPair<ParameterExpression, ParameterExpression>(
                        lambdaWithParameters.Parameters[positionalParameterReplacementEnumeratorCurrent.Key],
                        positionalParameterReplacementEnumeratorCurrent.Value);
                    sourceTargetPairsIndex++;
                }
                var parameterReplacer = new ParameterReplacingVisitor(sourceTargetPairs);
                visitedLambdaBody = parameterReplacer.Visit(lambdaWithParameters.Body);
                foreach (var replacedParameter in parameterReplacer.ReplacedSourceTargetPairs) {
                    var index = lambdaParameters.FindIndex(parameter => ReferenceEquals(parameter, replacedParameter.Source));
                    if (index >= 0) {
                        lambdaParameters[index] = replacedParameter.Target;
                    }
                }
            } else {
                visitedLambdaBody = lambdaWithParameters.Body;
            }
            var replacableNodes = new SourceTargetPair<Expression, Expression>[positionalConstants.Count];
            var positionalConstantsEnumerator = positionalConstants.GetEnumerator();
            var replacableNodesIndex = 0;
            while (positionalConstantsEnumerator.MoveNext()) {
                var positionalParameterReplacementEnumeratorCurrent = positionalConstantsEnumerator.Current;
                replacableNodes[replacableNodesIndex] = new SourceTargetPair<Expression, Expression>(
                    lambdaParameters[positionalParameterReplacementEnumeratorCurrent.Key],
                    Expression.Constant(positionalParameterReplacementEnumeratorCurrent.Value));
                replacableNodesIndex++;
            }
            var nodeReplacer = new NodeReplacingVisitor(replacableNodes);
            visitedLambdaBody = nodeReplacer.Visit(visitedLambdaBody)!;
            foreach (var replacedParameter in nodeReplacer.ReplacedSourceTargetPairs.Reverse()) {
                var index = lambdaParameters.FindIndex(parameter => ReferenceEquals(parameter, replacedParameter.Target));
                if (index >= 0) {
                    lambdaParameters.RemoveAt(index);
                }
            }
            positionalParameters = lambdaParameters;
            return visitedLambdaBody;
        }
public static Expression ReplaceParameterByConstantLambdaBody ( LambdaExpression lambdaWithParameters , IReadOnlyDictionary < int , ParameterExpression > ? positionalParameterReplacements , IReadOnlyDictionary < int , object ? > positionalConstants , out IReadOnlyList < ParameterExpression > positionalParameters ) { lambdaWithParameters = lambdaWithParameters ?? throw new ArgumentNullException ( nameof ( lambdaWithParameters ) ) ; positionalConstants = positionalConstants ?? throw new ArgumentNullException ( nameof ( positionalConstants ) ) ; var lambdaParameters = new List < ParameterExpression > ( lambdaWithParameters . Parameters ) ; Expression visitedLambdaBody ; if ( ! ( positionalParameterReplacements is null ) ) { var sourceTargetPairs = new SourceTargetPair < ParameterExpression , ParameterExpression > [ positionalParameterReplacements . Count ] ; var positionalParameterReplacementsEnumerator = positionalParameterReplacements . GetEnumerator ( ) ; var sourceTargetPairsIndex = 0 ; while ( positionalParameterReplacementsEnumerator . MoveNext ( ) ) { var positionalParameterReplacementEnumeratorCurrent = positionalParameterReplacementsEnumerator . Current ; sourceTargetPairs [ sourceTargetPairsIndex ] = new SourceTargetPair < ParameterExpression , ParameterExpression > ( lambdaWithParameters . Parameters [ positionalParameterReplacementEnumeratorCurrent . Key ] , positionalParameterReplacementEnumeratorCurrent . Value ) ; sourceTargetPairsIndex ++ ; } var parameterReplacer = new ParameterReplacingVisitor ( sourceTargetPairs ) ; visitedLambdaBody = parameterReplacer . Visit ( lambdaWithParameters . Body ) ; foreach ( var replacedParameter in parameterReplacer . ReplacedSourceTargetPairs ) { var index = lambdaParameters . FindIndex ( parameter => ReferenceEquals ( parameter , replacedParameter . Source ) ) ; if ( index >= 0 ) { lambdaParameters [ index ] = replacedParameter . Target ; } } } else { visitedLambdaBody = lambdaWithParameters . Body ; } var replacableNodes = new SourceTargetPair < Expression , Expression > [ positionalConstants . Count ] ; var positionalConstantsEnumerator = positionalConstants . GetEnumerator ( ) ; var replacableNodesIndex = 0 ; while ( positionalConstantsEnumerator . MoveNext ( ) ) { var positionalParameterReplacementEnumeratorCurrent = positionalConstantsEnumerator . Current ; replacableNodes [ replacableNodesIndex ] = new SourceTargetPair < Expression , Expression > ( lambdaParameters [ positionalParameterReplacementEnumeratorCurrent . Key ] , Expression . Constant ( positionalParameterReplacementEnumeratorCurrent . Value ) ) ; replacableNodesIndex ++ ; } var nodeReplacer = new NodeReplacingVisitor ( replacableNodes ) ; visitedLambdaBody = nodeReplacer . Visit ( visitedLambdaBody ) ! ; foreach ( var replacedParameter in nodeReplacer . ReplacedSourceTargetPairs . Reverse ( ) ) { var index = lambdaParameters . FindIndex ( parameter => ReferenceEquals ( parameter , replacedParameter . Target ) ) ; if ( index >= 0 ) { lambdaParameters . RemoveAt ( index ) ; } } positionalParameters = lambdaParameters ; return visitedLambdaBody ; }
Reduces parameter list by replacing the expression parameter expression
usages (of type ) with constant
expression crafted from .
Reduces parameter list by replacing the expression parameter expression usages ( of type ) with constant expression crafted from .
// After replacing parameter expression, you should update the references of lambda parameters. // Update lambda parameter by replaced one. // After replacing parameters by constants, you should remove those lambda parameters. // We assume that the first appearing expression got replaced first.
The body that got rewritten.
The body that got rewritten .
lambdaWithParameters
LambdaExpression
The lambda expression from which the body will be rewritten.
The lambda expression from which the body will be rewritten .
positionalParameterReplacements
IReadOnlyDictionary<int, ParameterExpression>?
Positional parameters that replace parameters before they may get replaced by
constants.
Positional parameters that replace parameters before they may get replaced by constants .
positionalConstants
IReadOnlyDictionary<int, object?>
IReadOnlyList<ParameterExpression>
out
constant
The value that will be used as constant.
The value that will be used as constant .