Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bind expressions to correct constructor parameter #557

Merged
merged 5 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
25 changes: 15 additions & 10 deletions src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1466,20 +1466,25 @@ private Expression CreateNewExpression(List<DynamicProperty> properties, List<Ex

Type[] propertyTypes = propertyInfos.Select(p => p.PropertyType).ToArray();
ConstructorInfo ctor = type.GetConstructor(propertyTypes);
if (ctor != null && ctor.GetParameters().Length == expressions.Count)
if (ctor != null)
{
var expressionsPromoted = new List<Expression>();

// Loop all expressions and promote if needed
for (int i = 0; i < propertyTypes.Length; i++)
var ctorParameters = ctor.GetParameters();
if (ctorParameters.Length == expressions.Count)
{
Type propertyType = propertyTypes[i];
var expressionsPromoted = new List<Expression>();
// Loop all expressions and promote if needed
for (int i = 0; i < ctorParameters.Length; i++)
{
Type propertyType = ctorParameters[i].ParameterType;
string cParameterName = ctorParameters[i].Name;
var propertyAndIndex = properties.Select((p, index) => new { p, index })
.First(p => p.p.Name == cParameterName && p.p.Type == propertyType);
// Promote from Type to Nullable Type if needed
expressionsPromoted.Add(_parsingConfig.ExpressionPromoter.Promote(expressions[propertyAndIndex.index], propertyType, true, true));
}

// Promote from Type to Nullable Type if needed
expressionsPromoted.Add(_parsingConfig.ExpressionPromoter.Promote(expressions[i], propertyType, true, true));
return Expression.New(ctor, expressionsPromoted, (IEnumerable<MemberInfo>)propertyInfos);
}

return Expression.New(ctor, expressionsPromoted, (IEnumerable<MemberInfo>)propertyInfos);
}

MemberBinding[] bindings = new MemberBinding[properties.Count];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq.Dynamic.Core.Parser;
using System.Collections.Generic;
using System.Linq.Dynamic.Core.Parser;
using System.Linq.Expressions;
using FluentAssertions;
using Xunit;
Expand Down Expand Up @@ -97,5 +98,28 @@ public void ParseTypeAccess_Via_Constructor_String_And_UriKind_To_Uri()
// Assert
expression.ToString().Should().Be("new Uri(\"https://www.example.com/\", Absolute)");
}

[Theory]
[InlineData("new(2 as b, 1 as a)", "new(1 as a, 2 as b)")]
public void ParseTypeAccess_Via_Constructor_DynamicType_To_String(string newExpression, string newExpression2)
{
// Arrange
var parameter = Expression.Parameter(typeof(int));
var parameter2 = Expression.Parameter(typeof(int));
var returnType = DynamicClassFactory.CreateType(new List<DynamicProperty> {
new DynamicProperty("a", typeof(int)),
new DynamicProperty("b", typeof(int))
});

// Act
var parser = new ExpressionParser(new[] { parameter, parameter2 }, newExpression, new object[] { }, ParsingConfig.Default);
var parser2 = new ExpressionParser(new[] { parameter, parameter2 }, newExpression2, new object[] { }, ParsingConfig.Default);

var expression = parser.Parse(returnType);
var expression2 = parser2.Parse(returnType);
// Assert
expression.ToString().Should().Be("new "+ returnType.Name + "(a = 1, b = 2)");
expression2.ToString().Should().Be("new "+ returnType.Name + "(a = 1, b = 2)");
}
}
}