Skip to content

Commit e925a09

Browse files
DynamicExpressionParser - Handle indexed properties with any number of indices in expression
1 parent 1cc4ea0 commit e925a09

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,15 +2358,18 @@ private Expression ParseElementAccess(Expression expr)
23582358

23592359
case 1:
23602360
var indexMethod = (MethodInfo)mb!;
2361-
var indexParameterType = indexMethod.GetParameters().First().ParameterType;
2361+
var indexMethodArguments = indexMethod.GetParameters();
23622362

2363-
var indexArgumentExpression = args[0]; // Indexer only has 1 parameter, so we can use args[0] here
2364-
if (indexParameterType != indexArgumentExpression.Type)
2363+
var indexArgumentExpressions = new Expression[args.Length];
2364+
for (var i = 0; i < indexMethodArguments.Length; ++i)
23652365
{
2366-
indexArgumentExpression = Expression.Convert(indexArgumentExpression, indexParameterType);
2366+
var indexParameterType = indexMethodArguments[i].ParameterType;
2367+
indexArgumentExpressions[i] = indexParameterType != args[i].Type
2368+
? Expression.Convert(args[i], indexParameterType)
2369+
: args[i];
23672370
}
23682371

2369-
return Expression.Call(expr, indexMethod, indexArgumentExpression);
2372+
return Expression.Call(expr, indexMethod, indexArgumentExpressions);
23702373

23712374
default:
23722375
throw ParseError(errorPos, Res.AmbiguousIndexerInvocation, TypeHelper.GetTypeName(expr.Type));

test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ public override HashSet<Type> GetCustomTypes()
7070
}
7171
}
7272

73+
private class ClassWithIndexers
74+
{
75+
public int this[int i1]
76+
{
77+
get => i1 + 1;
78+
}
79+
public string this[int i1, string i2]
80+
{
81+
get => i1 + "-" + i2;
82+
}
83+
}
84+
7385
private class ComplexParseLambda1Result
7486
{
7587
public int? Age;
@@ -660,6 +672,60 @@ public void DynamicExpressionParser_ParseLambda_Issue58()
660672
Check.That(result).Equals(42);
661673
}
662674

675+
[Fact]
676+
public void DynamicExpressionParser_ParseLambda_Indexer1D()
677+
{
678+
// Arrange
679+
var customTypeProvider = new Mock<IDynamicLinqCustomTypeProvider>();
680+
customTypeProvider.Setup(c => c.GetCustomTypes()).Returns([typeof(ClassWithIndexers)]);
681+
var config = new ParsingConfig
682+
{
683+
CustomTypeProvider = customTypeProvider.Object
684+
};
685+
var expressionParams = new[]
686+
{
687+
Expression.Parameter(typeof(ClassWithIndexers), "myObj")
688+
};
689+
690+
var myClassInstance = new ClassWithIndexers();
691+
var invokersMerge = new List<object> { myClassInstance };
692+
693+
// Act
694+
var expression = DynamicExpressionParser.ParseLambda(config, false, expressionParams, null, "myObj[3]");
695+
var del = expression.Compile();
696+
var result = del.DynamicInvoke(invokersMerge.ToArray());
697+
698+
// Assert
699+
Check.That(result).Equals(4);
700+
}
701+
702+
[Fact]
703+
public void DynamicExpressionParser_ParseLambda_Indexer2D()
704+
{
705+
// Arrange
706+
var customTypeProvider = new Mock<IDynamicLinqCustomTypeProvider>();
707+
customTypeProvider.Setup(c => c.GetCustomTypes()).Returns([typeof(ClassWithIndexers)]);
708+
var config = new ParsingConfig
709+
{
710+
CustomTypeProvider = customTypeProvider.Object
711+
};
712+
var expressionParams = new[]
713+
{
714+
Expression.Parameter(typeof(ClassWithIndexers), "myObj")
715+
};
716+
717+
var myClassInstance = new ClassWithIndexers();
718+
var invokersMerge = new List<object> { myClassInstance };
719+
720+
// Act
721+
var expression = DynamicExpressionParser.ParseLambda(config, false, expressionParams, null, "myObj[3,\"1\"]");
722+
var del = expression.Compile();
723+
var result = del.DynamicInvoke(invokersMerge.ToArray());
724+
725+
// Assert
726+
Check.That(result).Equals("3-1");
727+
}
728+
663729
[Fact]
664730
public void DynamicExpressionParser_ParseLambda_DuplicateParameterNames_ThrowsException()
665731
{

0 commit comments

Comments
 (0)