44 using System . Collections . Generic ;
55 using System . Linq ;
66 using System . Linq . Expressions ;
7+ using static System . Linq . Expressions . ExpressionType ;
78
89 internal static partial class ExpressionExtensions
910 {
10- public static Expression ReplaceParameterWith ( this LambdaExpression lambda , Expression replacement )
11- => ReplaceParametersWith ( lambda , replacement ) ;
12-
1311 public static Expression ReplaceParametersWith ( this LambdaExpression lambda , params Expression [ ] replacements )
1412 {
1513 if ( lambda . Parameters . HasOne ( ) )
1614 {
17- return lambda . Body . Replace ( lambda . Parameters [ 0 ] , replacements [ 0 ] ) ;
15+ return lambda . ReplaceParameterWith ( replacements . First ( ) ) ;
1816 }
1917
2018 var replacementsByParameter = lambda
2119 . Parameters
22- . Cast < Expression > ( )
2320 . Select ( ( p , i ) => new { Parameter = p , Replacement = replacements [ i ] } )
24- . ToDictionary ( d => d . Parameter , d => d . Replacement ) ;
21+ . ToDictionary ( d => ( Expression ) d . Parameter , d => d . Replacement ) ;
2522
2623 return lambda . Body . Replace ( replacementsByParameter ) ;
2724 }
2825
26+ public static Expression ReplaceParameterWith ( this LambdaExpression lambda , Expression replacement )
27+ => ReplaceParameter ( lambda . Body , lambda . Parameters [ 0 ] , replacement ) ;
28+
29+ private static TExpression ReplaceParameter < TExpression > (
30+ TExpression expression ,
31+ Expression parameter ,
32+ Expression replacement )
33+ where TExpression : Expression
34+ {
35+ return new ParameterReplacer ( parameter , replacement ) . ReplaceIn ( expression ) ;
36+ }
37+
2938 public static TExpression Replace < TExpression > (
3039 this TExpression expression ,
3140 Expression target ,
@@ -38,6 +47,11 @@ public static TExpression Replace<TExpression>(
3847 return null ;
3948 }
4049
50+ if ( target . NodeType == Parameter )
51+ {
52+ return ReplaceParameter ( expression , target , replacement ) ;
53+ }
54+
4155 return new ExpressionReplacer (
4256 target ,
4357 replacement ,
@@ -65,6 +79,27 @@ public static TExpression Replace<TExpression>(
6579 return replacer . Replace < TExpression > ( expression ) ;
6680 }
6781
82+ private class ParameterReplacer : ExpressionVisitor
83+ {
84+ private readonly Expression _parameterToReplace ;
85+ private readonly Expression _replacement ;
86+
87+ public ParameterReplacer ( Expression parameterToReplace , Expression replacement )
88+ {
89+ _parameterToReplace = parameterToReplace ;
90+ _replacement = replacement ;
91+ }
92+
93+ public TExpression ReplaceIn < TExpression > ( TExpression expression )
94+ where TExpression : Expression
95+ {
96+ return VisitAndConvert ( expression , nameof ( ParameterReplacer ) ) ;
97+ }
98+
99+ protected override Expression VisitParameter ( ParameterExpression parameter )
100+ => parameter == _parameterToReplace ? _replacement : parameter ;
101+ }
102+
68103 private class ExpressionReplacer
69104 {
70105 private readonly Dictionary < Expression , Expression > _replacementsByTarget ;
@@ -99,82 +134,82 @@ private Expression ReplaceIn(Expression expression)
99134 {
100135 switch ( expression . NodeType )
101136 {
102- case ExpressionType . Add :
103- case ExpressionType . And :
104- case ExpressionType . AndAlso :
105- case ExpressionType . Assign :
106- case ExpressionType . Coalesce :
107- case ExpressionType . Divide :
108- case ExpressionType . Equal :
109- case ExpressionType . GreaterThan :
110- case ExpressionType . GreaterThanOrEqual :
111- case ExpressionType . LessThan :
112- case ExpressionType . LessThanOrEqual :
113- case ExpressionType . Modulo :
114- case ExpressionType . Multiply :
115- case ExpressionType . NotEqual :
116- case ExpressionType . Or :
117- case ExpressionType . OrElse :
118- case ExpressionType . Subtract :
137+ case Add :
138+ case And :
139+ case AndAlso :
140+ case Assign :
141+ case Coalesce :
142+ case Divide :
143+ case Equal :
144+ case GreaterThan :
145+ case GreaterThanOrEqual :
146+ case LessThan :
147+ case LessThanOrEqual :
148+ case Modulo :
149+ case Multiply :
150+ case NotEqual :
151+ case Or :
152+ case OrElse :
153+ case Subtract :
119154 return ReplaceIn ( ( BinaryExpression ) expression ) ;
120155
121- case ExpressionType . Block :
156+ case Block :
122157 return ReplaceIn ( ( BlockExpression ) expression ) ;
123158
124- case ExpressionType . Call :
159+ case Call :
125160 return ReplaceIn ( ( MethodCallExpression ) expression ) ;
126161
127- case ExpressionType . Conditional :
162+ case Conditional :
128163 return ReplaceIn ( ( ConditionalExpression ) expression ) ;
129164
130165 case ExpressionType . Convert :
131- case ExpressionType . IsFalse :
132- case ExpressionType . IsTrue :
133- case ExpressionType . Not :
134- case ExpressionType . Throw :
135- case ExpressionType . TypeAs :
166+ case IsFalse :
167+ case IsTrue :
168+ case Not :
169+ case Throw :
170+ case TypeAs :
136171 return ReplaceIn ( ( UnaryExpression ) expression ) ;
137172
138- case ExpressionType . Goto :
173+ case Goto :
139174 return ReplaceIn ( ( GotoExpression ) expression ) ;
140175
141- case ExpressionType . Index :
176+ case Index :
142177 return ReplaceIn ( ( IndexExpression ) expression ) ;
143178
144- case ExpressionType . Invoke :
179+ case Invoke :
145180 return ReplaceIn ( ( InvocationExpression ) expression ) ;
146181
147- case ExpressionType . Label :
182+ case Label :
148183 return ReplaceIn ( ( LabelExpression ) expression ) ;
149184
150- case ExpressionType . Lambda :
185+ case Lambda :
151186 return ReplaceIn ( ( LambdaExpression ) expression ) ;
152187
153- case ExpressionType . ListInit :
188+ case ListInit :
154189 return ReplaceIn ( ( ListInitExpression ) expression ) ;
155190
156- case ExpressionType . Loop :
191+ case Loop :
157192 return ReplaceIn ( ( LoopExpression ) expression ) ;
158193
159- case ExpressionType . MemberAccess :
194+ case MemberAccess :
160195 return ReplaceIn ( ( MemberExpression ) expression ) ;
161196
162- case ExpressionType . MemberInit :
197+ case MemberInit :
163198 return ReplaceIn ( ( MemberInitExpression ) expression ) ;
164199
165- case ExpressionType . New :
200+ case New :
166201 return ReplaceIn ( ( NewExpression ) expression ) ;
167202
168- case ExpressionType . NewArrayInit :
203+ case NewArrayInit :
169204 return ReplaceIn ( ( NewArrayExpression ) expression ) ;
170205
171- case ExpressionType . Parameter :
206+ case Parameter :
172207 return ReplaceIn ( ( ParameterExpression ) expression ) ;
173208
174- case ExpressionType . TypeIs :
209+ case TypeIs :
175210 return ReplaceIn ( ( TypeBinaryExpression ) expression ) ;
176211
177- case ExpressionType . Try :
212+ case Try :
178213 return ReplaceIn ( ( TryExpression ) expression ) ;
179214 }
180215
@@ -293,7 +328,7 @@ private Expression ReplaceIn<TExpression>(TExpression expression, Func<TExpressi
293328 return null ;
294329 }
295330
296- if ( expression . NodeType == ExpressionType . Default )
331+ if ( expression . NodeType == Default )
297332 {
298333 return expression ;
299334 }
0 commit comments