@@ -1319,7 +1319,32 @@ private Expression GetMember(Expression expression, MemberInfo member, Expressio
13191319 var memberIndex = newExpression . Members . IndexOf ( member ) ;
13201320 if ( memberIndex < 0 )
13211321 throw new InvalidOperationException ( string . Format ( Strings . ExCouldNotGetMemberXFromExpression , member ) ) ;
1322- var argument = Visit ( newExpression . Arguments [ memberIndex ] ) ;
1322+ var argument = newExpression . Arguments [ memberIndex ] ;
1323+ var currentLambda = state . CurrentLambda ;
1324+ if ( ! ( currentLambda is null ) && context . Bindings . TryGetValue ( currentLambda . Parameters [ 0 ] , out var projection ) ) {
1325+ // Here, we try to detect whether the expression has already visited, in such cases
1326+ // re-visiting it may cause issues. For instance, .OrderBy(x=>x.SomeField) translation
1327+ // gets projection of already visited source and substitutes parameter 'x' access with
1328+ // that projection. For now TranslatorState.ShouldOmitConvertToObject == true, is a marker
1329+ // of OrderBy visiting, because it is the only place that sets 'true' to the property,
1330+ // but we can't rely on it for future-proof solution.
1331+
1332+ // Knowing that parameter-to-projection binding happens when expression has visited,
1333+ // we assume this check is enough for certain cases, probably not for all of them.
1334+ // We can't deny visiting of the argument for all the cases because of chance to break
1335+ // some cases we could not imagine at the time of changes
1336+ switch ( argument . NodeType ) {
1337+ case ExpressionType . TypeAs :
1338+ case ExpressionType . Convert :
1339+ case ExpressionType . ConvertChecked :
1340+ if ( argument . Type == typeof ( object ) && state . ShouldOmitConvertToObject )
1341+ argument = argument . StripCasts ( ) ;
1342+ break ;
1343+ }
1344+ }
1345+ else {
1346+ argument = Visit ( argument ) ;
1347+ }
13231348 return isMarker ? new MarkerExpression ( argument , markerType ) : argument ;
13241349 }
13251350
0 commit comments