Skip to content

Commit 6f974f0

Browse files
committed
Fix MethodFinder.FirstIsBetterThanSecond
1 parent 99eb4c9 commit 6f974f0

File tree

3 files changed

+84
-8
lines changed

3 files changed

+84
-8
lines changed

src/System.Linq.Dynamic.Core/DynamicClassFactory.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ private static Type EmitType(IList<DynamicProperty> properties, bool createParam
296296
var equalityType = fieldTypeIsAccessible ? fieldType : typeof(object);
297297
var equalityComparerT = EqualityComparer.MakeGenericType(equalityType);
298298

299-
// Equals()
299+
// Implement Equals();
300300
MethodInfo equalityComparerTDefault = equalityComparerT.GetMethod("get_Default", BindingFlags.Static | BindingFlags.Public)!;
301301
MethodInfo equalityComparerTEquals = equalityComparerT.GetMethod(nameof(EqualityComparer.Equals), BindingFlags.Instance | BindingFlags.Public, null, [equalityType, equalityType], null)!;
302302

@@ -306,13 +306,21 @@ private static Type EmitType(IList<DynamicProperty> properties, bool createParam
306306
ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault);
307307
ilgeneratorEquals.Emit(OpCodes.Ldarg_0);
308308
ilgeneratorEquals.Emit(OpCodes.Ldfld, fieldBuilders[i]);
309-
if (!fieldTypeIsAccessible) ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
309+
if (!fieldTypeIsAccessible)
310+
{
311+
ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
312+
}
313+
310314
ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
311315
ilgeneratorEquals.Emit(OpCodes.Ldfld, fieldBuilders[i]);
312-
if (!fieldTypeIsAccessible) ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
316+
if (!fieldTypeIsAccessible)
317+
{
318+
ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
319+
}
320+
313321
ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals);
314322

315-
// GetHashCode();
323+
// Implement GetHashCode();
316324
MethodInfo equalityComparerTGetHashCode = equalityComparerT.GetMethod(nameof(EqualityComparer.GetHashCode), BindingFlags.Instance | BindingFlags.Public, null, [equalityType], null)!;
317325
ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
318326
ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295);
@@ -321,11 +329,15 @@ private static Type EmitType(IList<DynamicProperty> properties, bool createParam
321329
ilgeneratorGetHashCode.Emit(OpCodes.Call, equalityComparerTDefault);
322330
ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0);
323331
ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fieldBuilders[i]);
324-
if (!fieldTypeIsAccessible) ilgeneratorGetHashCode.Emit(OpCodes.Box, fieldType);
332+
if (!fieldTypeIsAccessible)
333+
{
334+
ilgeneratorGetHashCode.Emit(OpCodes.Box, fieldType);
335+
}
336+
325337
ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, equalityComparerTGetHashCode);
326338
ilgeneratorGetHashCode.Emit(OpCodes.Add);
327339

328-
// ToString();
340+
// Implement ToString();
329341
ilgeneratorToString.Emit(OpCodes.Ldloc_0);
330342
ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? $"{{ {fieldName} = " : $", {fieldName} = ");
331343
ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);

src/System.Linq.Dynamic.Core/Parser/SupportedMethods/MethodFinder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,8 @@ private static bool FirstIsBetterThanSecond(Expression[] args, MethodData first,
342342
}
343343

344344
var better = false;
345-
for (var i = 0; i < args.Length; i++)
345+
var maxLength = Math.Min(first.Parameters.Length, second.Parameters.Length);
346+
for (var i = 0; i < maxLength; i++)
346347
{
347348
var result = CompareConversions(args[i].Type, first.Parameters[i].ParameterType, second.Parameters[i].ParameterType);
348349

test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ public void Parse_When_PrioritizePropertyOrFieldOverTheType_IsTrue(string expres
390390
CustomTypeProvider = _dynamicTypeProviderMock.Object,
391391
AllowEqualsAndToStringMethodsOnObject = true
392392
};
393-
ParameterExpression[] parameters = [ ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "company") ];
393+
ParameterExpression[] parameters = [ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "company")];
394394
var sut = new ExpressionParser(parameters, expression, null, config);
395395

396396
// Act
@@ -462,6 +462,69 @@ public void Parse_StringConcat(string expression, string result)
462462
parsedExpression.Should().Be(result);
463463
}
464464

465+
[Fact]
466+
public void Parse_StringConcat3Strings()
467+
{
468+
// Arrange
469+
var parameters = new[]
470+
{
471+
Expression.Parameter(typeof(string), "x"),
472+
Expression.Parameter(typeof(string), "y")
473+
};
474+
475+
var parser = new ExpressionParser(
476+
parameters,
477+
"string.Concat(x, \" - \", y)",
478+
values: null,
479+
parsingConfig: null);
480+
481+
// Act
482+
var expression = parser.Parse(typeof(string));
483+
484+
// Assert
485+
expression.ToString().Should().Be("Concat(x, \" - \", y)");
486+
487+
// Compile and invoke
488+
var lambda = Expression.Lambda<Func<string, string, string>>(expression, parameters);
489+
var compiled = lambda.Compile();
490+
var result = compiled("hello", "world");
491+
492+
// Assert
493+
result.Should().Be("hello - world");
494+
}
495+
496+
[Fact]
497+
public void Parse_StringConcat4Strings()
498+
{
499+
// Arrange
500+
var parameters = new[]
501+
{
502+
Expression.Parameter(typeof(string), "x"),
503+
Expression.Parameter(typeof(string), "y"),
504+
Expression.Parameter(typeof(string), "z")
505+
};
506+
507+
var parser = new ExpressionParser(
508+
parameters,
509+
"string.Concat(x, \" - \", y, z)",
510+
values: null,
511+
parsingConfig: null);
512+
513+
// Act
514+
var expression = parser.Parse(typeof(string));
515+
516+
// Assert
517+
expression.ToString().Should().Be("Concat(x, \" - \", y, z)");
518+
519+
// Compile and invoke
520+
var lambda = Expression.Lambda<Func<string, string, string, string>>(expression, parameters);
521+
var compiled = lambda.Compile();
522+
var result = compiled("hello", "earth", "moon");
523+
524+
// Assert
525+
result.Should().Be("hello - earthmoon");
526+
}
527+
465528
[Fact]
466529
public void Parse_InvalidExpressionShouldThrowArgumentException()
467530
{

0 commit comments

Comments
 (0)