Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/System.Linq.Dynamic.Core/DynamicClassFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ private static Type EmitType(IList<DynamicProperty> properties, bool createParam
var equalityType = fieldTypeIsAccessible ? fieldType : typeof(object);
var equalityComparerT = EqualityComparer.MakeGenericType(equalityType);

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

Expand All @@ -306,13 +306,21 @@ private static Type EmitType(IList<DynamicProperty> properties, bool createParam
ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault);
ilgeneratorEquals.Emit(OpCodes.Ldarg_0);
ilgeneratorEquals.Emit(OpCodes.Ldfld, fieldBuilders[i]);
if (!fieldTypeIsAccessible) ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
if (!fieldTypeIsAccessible)
{
ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
}

ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
ilgeneratorEquals.Emit(OpCodes.Ldfld, fieldBuilders[i]);
if (!fieldTypeIsAccessible) ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
if (!fieldTypeIsAccessible)
{
ilgeneratorEquals.Emit(OpCodes.Box, fieldType);
}

ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals);

// GetHashCode();
// Implement GetHashCode();
MethodInfo equalityComparerTGetHashCode = equalityComparerT.GetMethod(nameof(EqualityComparer.GetHashCode), BindingFlags.Instance | BindingFlags.Public, null, [equalityType], null)!;
ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295);
Expand All @@ -321,11 +329,15 @@ private static Type EmitType(IList<DynamicProperty> properties, bool createParam
ilgeneratorGetHashCode.Emit(OpCodes.Call, equalityComparerTDefault);
ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0);
ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fieldBuilders[i]);
if (!fieldTypeIsAccessible) ilgeneratorGetHashCode.Emit(OpCodes.Box, fieldType);
if (!fieldTypeIsAccessible)
{
ilgeneratorGetHashCode.Emit(OpCodes.Box, fieldType);
}

ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, equalityComparerTGetHashCode);
ilgeneratorGetHashCode.Emit(OpCodes.Add);

// ToString();
// Implement ToString();
ilgeneratorToString.Emit(OpCodes.Ldloc_0);
ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? $"{{ {fieldName} = " : $", {fieldName} = ");
ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ private static bool FirstIsBetterThanSecond(Expression[] args, MethodData first,
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ public void Parse_When_PrioritizePropertyOrFieldOverTheType_IsTrue(string expres
CustomTypeProvider = _dynamicTypeProviderMock.Object,
AllowEqualsAndToStringMethodsOnObject = true
};
ParameterExpression[] parameters = [ ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "company") ];
ParameterExpression[] parameters = [ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "company")];
var sut = new ExpressionParser(parameters, expression, null, config);

// Act
Expand Down Expand Up @@ -462,6 +462,69 @@ public void Parse_StringConcat(string expression, string result)
parsedExpression.Should().Be(result);
}

[Fact]
public void Parse_StringConcat3Strings()
{
// Arrange
var parameters = new[]
{
Expression.Parameter(typeof(string), "x"),
Expression.Parameter(typeof(string), "y")
};

var parser = new ExpressionParser(
parameters,
"string.Concat(x, \" - \", y)",
values: null,
parsingConfig: null);

// Act
var expression = parser.Parse(typeof(string));

// Assert
expression.ToString().Should().Be("Concat(x, \" - \", y)");

// Compile and invoke
var lambda = Expression.Lambda<Func<string, string, string>>(expression, parameters);
var compiled = lambda.Compile();
var result = compiled("hello", "world");

// Assert
result.Should().Be("hello - world");
}

[Fact]
public void Parse_StringConcat4Strings()
{
// Arrange
var parameters = new[]
{
Expression.Parameter(typeof(string), "x"),
Expression.Parameter(typeof(string), "y"),
Expression.Parameter(typeof(string), "z")
};

var parser = new ExpressionParser(
parameters,
"string.Concat(x, \" - \", y, z)",
values: null,
parsingConfig: null);

// Act
var expression = parser.Parse(typeof(string));

// Assert
expression.ToString().Should().Be("Concat(x, \" - \", y, z)");

// Compile and invoke
var lambda = Expression.Lambda<Func<string, string, string, string>>(expression, parameters);
var compiled = lambda.Compile();
var result = compiled("hello", "earth", "moon");

// Assert
result.Should().Be("hello - earthmoon");
}

[Fact]
public void Parse_InvalidExpressionShouldThrowArgumentException()
{
Expand Down
Loading