diff --git a/src-console/ConsoleApp_net452_EF6/Program.cs b/src-console/ConsoleApp_net452_EF6/Program.cs
index a74cd8dc..e4ee81b3 100644
--- a/src-console/ConsoleApp_net452_EF6/Program.cs
+++ b/src-console/ConsoleApp_net452_EF6/Program.cs
@@ -23,8 +23,6 @@ static void Main(string[] args)
var found3 = context.Employees.FirstOrDefault($"EmployeeNumber > @0", em);
Console.WriteLine($"found3 : {found3.Id} - {found3.EmployeeNumber}");
- return;
-
string search = "2";
var expected = context.Employees.Where(e => System.Data.Entity.SqlServer.SqlFunctions.StringConvert((double)e.EmployeeNumber).Contains(search)).ToArray();
foreach (var emp in expected)
diff --git a/src/System.Linq.Dynamic.Core/Compatibility/ExpressionVisitor.cs b/src/System.Linq.Dynamic.Core/Compatibility/ExpressionVisitor.cs
new file mode 100644
index 00000000..475cdd7b
--- /dev/null
+++ b/src/System.Linq.Dynamic.Core/Compatibility/ExpressionVisitor.cs
@@ -0,0 +1,396 @@
+#if NET35
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace System.Linq.Expressions
+{
+ ///
+ /// Code copied from https://blogs.msdn.microsoft.com/mattwar/2007/07/31/linq-building-an-iqueryable-provider-part-ii/
+ ///
+ internal abstract class ExpressionVisitor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ protected ExpressionVisitor()
+ {
+ }
+
+ protected virtual Expression Visit(Expression exp)
+ {
+ if (exp == null)
+ return exp;
+
+ switch (exp.NodeType)
+ {
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.Not:
+ case ExpressionType.Convert:
+ case ExpressionType.ConvertChecked:
+ case ExpressionType.ArrayLength:
+ case ExpressionType.Quote:
+ case ExpressionType.TypeAs:
+ return VisitUnary((UnaryExpression)exp);
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ case ExpressionType.Divide:
+ case ExpressionType.Modulo:
+ case ExpressionType.And:
+ case ExpressionType.AndAlso:
+ case ExpressionType.Or:
+ case ExpressionType.OrElse:
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ case ExpressionType.Coalesce:
+ case ExpressionType.ArrayIndex:
+ case ExpressionType.RightShift:
+ case ExpressionType.LeftShift:
+ case ExpressionType.ExclusiveOr:
+ return VisitBinary((BinaryExpression)exp);
+ case ExpressionType.TypeIs:
+ return VisitTypeIs((TypeBinaryExpression)exp);
+ case ExpressionType.Conditional:
+ return VisitConditional((ConditionalExpression)exp);
+ case ExpressionType.Constant:
+ return VisitConstant((ConstantExpression)exp);
+ case ExpressionType.Parameter:
+ return VisitParameter((ParameterExpression)exp);
+ case ExpressionType.MemberAccess:
+ return VisitMemberAccess((MemberExpression)exp);
+ case ExpressionType.Call:
+ return VisitMethodCall((MethodCallExpression)exp);
+ case ExpressionType.Lambda:
+ return VisitLambda((LambdaExpression)exp);
+ case ExpressionType.New:
+ return VisitNew((NewExpression)exp);
+ case ExpressionType.NewArrayInit:
+ case ExpressionType.NewArrayBounds:
+ return VisitNewArray((NewArrayExpression)exp);
+ case ExpressionType.Invoke:
+ return VisitInvocation((InvocationExpression)exp);
+ case ExpressionType.MemberInit:
+ return VisitMemberInit((MemberInitExpression)exp);
+ case ExpressionType.ListInit:
+ return VisitListInit((ListInitExpression)exp);
+ default:
+ throw new Exception(string.Format("Unhandled expression type: '{0}'", exp.NodeType));
+ }
+ }
+
+ protected virtual MemberBinding VisitBinding(MemberBinding binding)
+ {
+ switch (binding.BindingType)
+ {
+ case MemberBindingType.Assignment:
+ return VisitMemberAssignment((MemberAssignment)binding);
+ case MemberBindingType.MemberBinding:
+ return VisitMemberMemberBinding((MemberMemberBinding)binding);
+ case MemberBindingType.ListBinding:
+ return VisitMemberListBinding((MemberListBinding)binding);
+ default:
+ throw new Exception(string.Format("Unhandled binding type '{0}'", binding.BindingType));
+ }
+ }
+
+ protected virtual ElementInit VisitElementInitializer(ElementInit initializer)
+ {
+ ReadOnlyCollection arguments = this.VisitExpressionList(initializer.Arguments);
+ if (arguments != initializer.Arguments)
+ {
+ return Expression.ElementInit(initializer.AddMethod, arguments);
+ }
+
+ return initializer;
+ }
+
+ protected virtual Expression VisitUnary(UnaryExpression u)
+ {
+ Expression operand = Visit(u.Operand);
+ if (operand != u.Operand)
+ {
+ return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method);
+ }
+
+ return u;
+ }
+
+ protected virtual Expression VisitBinary(BinaryExpression b)
+ {
+ Expression left = Visit(b.Left);
+ Expression right = Visit(b.Right);
+ Expression conversion = Visit(b.Conversion);
+ if (left != b.Left || right != b.Right || conversion != b.Conversion)
+ {
+ if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null)
+ return Expression.Coalesce(left, right, conversion as LambdaExpression);
+ else
+ return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
+ }
+
+ return b;
+ }
+
+ protected virtual Expression VisitTypeIs(TypeBinaryExpression b)
+ {
+ Expression expr = Visit(b.Expression);
+ if (expr != b.Expression)
+ {
+ return Expression.TypeIs(expr, b.TypeOperand);
+ }
+
+ return b;
+ }
+
+ protected virtual Expression VisitConstant(ConstantExpression c)
+ {
+ return c;
+ }
+
+ protected virtual Expression VisitConditional(ConditionalExpression c)
+ {
+ Expression test = Visit(c.Test);
+ Expression ifTrue = Visit(c.IfTrue);
+ Expression ifFalse = Visit(c.IfFalse);
+ if (test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse)
+ {
+ return Expression.Condition(test, ifTrue, ifFalse);
+ }
+
+ return c;
+ }
+
+ protected virtual Expression VisitParameter(ParameterExpression p)
+ {
+ return p;
+ }
+
+ protected virtual Expression VisitMemberAccess(MemberExpression m)
+ {
+ Expression exp = Visit(m.Expression);
+ if (exp != m.Expression)
+ {
+ return Expression.MakeMemberAccess(exp, m.Member);
+ }
+
+ return m;
+ }
+
+ protected virtual Expression VisitMethodCall(MethodCallExpression m)
+ {
+ Expression obj = Visit(m.Object);
+ IEnumerable args = this.VisitExpressionList(m.Arguments);
+ if (obj != m.Object || args != m.Arguments)
+ {
+ return Expression.Call(obj, m.Method, args);
+ }
+
+ return m;
+ }
+
+ protected virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCollection original)
+ {
+ List list = null;
+ for (int i = 0, n = original.Count; i < n; i++)
+ {
+ Expression p = this.Visit(original[i]);
+ if (list != null)
+ {
+ list.Add(p);
+ }
+ else if (p != original[i])
+ {
+ list = new List(n);
+ for (int j = 0; j < i; j++)
+ {
+ list.Add(original[j]);
+ }
+
+ list.Add(p);
+ }
+ }
+
+ if (list != null)
+ {
+ return list.AsReadOnly();
+ }
+
+ return original;
+ }
+
+ protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
+ {
+ Expression e = Visit(assignment.Expression);
+ if (e != assignment.Expression)
+ {
+ return Expression.Bind(assignment.Member, e);
+ }
+
+ return assignment;
+ }
+
+ protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
+ {
+ IEnumerable bindings = this.VisitBindingList(binding.Bindings);
+ if (bindings != binding.Bindings)
+ {
+ return Expression.MemberBind(binding.Member, bindings);
+ }
+
+ return binding;
+ }
+
+ protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
+ {
+ IEnumerable initializers = this.VisitElementInitializerList(binding.Initializers);
+ if (initializers != binding.Initializers)
+ {
+ return Expression.ListBind(binding.Member, initializers);
+ }
+
+ return binding;
+ }
+
+ protected virtual IEnumerable VisitBindingList(ReadOnlyCollection original)
+ {
+ List list = null;
+ for (int i = 0, n = original.Count; i < n; i++)
+ {
+ MemberBinding b = this.VisitBinding(original[i]);
+ if (list != null)
+ {
+ list.Add(b);
+ }
+ else if (b != original[i])
+ {
+ list = new List(n);
+ for (int j = 0; j < i; j++)
+ {
+ list.Add(original[j]);
+ }
+
+ list.Add(b);
+ }
+ }
+
+ if (list != null)
+ return list;
+ return original;
+ }
+
+ protected virtual IEnumerable VisitElementInitializerList(ReadOnlyCollection original)
+ {
+ List list = null;
+ for (int i = 0, n = original.Count; i < n; i++)
+ {
+ ElementInit init = this.VisitElementInitializer(original[i]);
+ if (list != null)
+ {
+ list.Add(init);
+ }
+ else if (init != original[i])
+ {
+ list = new List(n);
+ for (int j = 0; j < i; j++)
+ {
+ list.Add(original[j]);
+ }
+
+ list.Add(init);
+ }
+ }
+
+ if (list != null)
+ return list;
+ return original;
+ }
+
+ protected virtual Expression VisitLambda(LambdaExpression lambda)
+ {
+ Expression body = Visit(lambda.Body);
+ if (body != lambda.Body)
+ {
+ return Expression.Lambda(lambda.Type, body, lambda.Parameters);
+ }
+
+ return lambda;
+ }
+
+ protected virtual NewExpression VisitNew(NewExpression nex)
+ {
+ IEnumerable args = this.VisitExpressionList(nex.Arguments);
+ if (args != nex.Arguments)
+ {
+ if (nex.Members != null)
+ return Expression.New(nex.Constructor, args, nex.Members);
+ else
+ return Expression.New(nex.Constructor, args);
+ }
+
+ return nex;
+ }
+
+ protected virtual Expression VisitMemberInit(MemberInitExpression init)
+ {
+ NewExpression n = VisitNew(init.NewExpression);
+ IEnumerable bindings = this.VisitBindingList(init.Bindings);
+ if (n != init.NewExpression || bindings != init.Bindings)
+ {
+ return Expression.MemberInit(n, bindings);
+ }
+
+ return init;
+ }
+
+ protected virtual Expression VisitListInit(ListInitExpression init)
+ {
+ NewExpression n = VisitNew(init.NewExpression);
+ IEnumerable initializers = this.VisitElementInitializerList(init.Initializers);
+ if (n != init.NewExpression || initializers != init.Initializers)
+ {
+ return Expression.ListInit(n, initializers);
+ }
+
+ return init;
+ }
+
+ protected virtual Expression VisitNewArray(NewArrayExpression na)
+ {
+ IEnumerable exprs = this.VisitExpressionList(na.Expressions);
+ if (exprs != na.Expressions)
+ {
+ if (na.NodeType == ExpressionType.NewArrayInit)
+ {
+ return Expression.NewArrayInit(na.Type.GetElementType(), exprs);
+ }
+ else
+ {
+ return Expression.NewArrayBounds(na.Type.GetElementType(), exprs);
+ }
+ }
+
+ return na;
+ }
+
+ protected virtual Expression VisitInvocation(InvocationExpression iv)
+ {
+ IEnumerable args = this.VisitExpressionList(iv.Arguments);
+ Expression expr = Visit(iv.Expression);
+ if (args != iv.Arguments || expr != iv.Expression)
+ {
+ return Expression.Invoke(expr, args);
+ }
+
+ return iv;
+ }
+ }
+}
+#endif
diff --git a/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs b/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs
index 327901df..fa5ab9f1 100644
--- a/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs
+++ b/src/System.Linq.Dynamic.Core/DynamicExpressionParser.cs
@@ -1,7 +1,9 @@
using System.Linq.Dynamic.Core.Parser;
+using System.Linq.Dynamic.Core.Util;
using JetBrains.Annotations;
using System.Linq.Dynamic.Core.Validation;
using System.Linq.Expressions;
+using System.Collections.Generic;
namespace System.Linq.Dynamic.Core
{
@@ -63,7 +65,19 @@ public static LambdaExpression ParseLambda([CanBeNull] ParsingConfig parsingConf
var parser = new ExpressionParser(parameters, expression, values, parsingConfig);
- return Expression.Lambda(parser.Parse(resultType, createParameterCtor), parameters);
+ var parsedExpression = parser.Parse(resultType, createParameterCtor);
+
+ if (parsingConfig != null && parsingConfig.RenameParameterExpression && parameters.Length == 1)
+ {
+ var renamer = new ParameterExpressionRenamer(parser.ItName);
+ parsedExpression = renamer.Rename(parsedExpression, out ParameterExpression newParameterExpression);
+
+ return Expression.Lambda(parsedExpression, new[] { newParameterExpression });
+ }
+ else
+ {
+ return Expression.Lambda(parsedExpression, parameters);
+ }
}
///
diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
index 9b513588..8383631b 100644
--- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
@@ -38,6 +38,11 @@ public class ExpressionParser
private Type _resultType;
private bool _createParameterCtor;
+ ///
+ /// Gets name for the `it` field. By default this is set to the KeyWord value "it".
+ ///
+ public string ItName { get; private set; } = KeywordsHelper.KEYWORD_IT;
+
///
/// Initializes a new instance of the class.
///
@@ -1512,6 +1517,14 @@ Expression ParseMemberAccess(Type type, Expression instance)
{
// This might be an internal variable for use within a lambda expression, so store it as such
_internals.Add(id, _it);
+
+ // Also store ItName (only once)
+ if (string.Equals(ItName, KeywordsHelper.KEYWORD_IT))
+ {
+ ItName = id;
+ }
+
+ // next
_textParser.NextToken();
return ParseConditionalOperator();
diff --git a/src/System.Linq.Dynamic.Core/ParsingConfig.cs b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
index bebd87d4..a2760a86 100644
--- a/src/System.Linq.Dynamic.Core/ParsingConfig.cs
+++ b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
@@ -4,7 +4,7 @@
namespace System.Linq.Dynamic.Core
{
///
- /// Configuration class for Dynamic Linq.
+ /// Configuration class for System.Linq.Dynamic.Core.
///
public class ParsingConfig
{
@@ -71,19 +71,20 @@ public IExpressionPromoter ExpressionPromoter
///
/// Determines if the context keywords (it, parent, and root) are valid and usable inside a Dynamic Linq string expression.
/// Does not affect the usability of the equivalent context symbols ($, ^ and ~).
+ /// Default value is true.
///
public bool AreContextKeywordsEnabled { get; set; } = true;
///
- /// Gets or sets a value indicating whether to use dynamic object class for anonymous types.
+ /// Gets or sets a value indicating whether to use dynamic object class for anonymous types. Default value is false.
///
- public bool UseDynamicObjectClassForAnonymousTypes { get; set; }
+ public bool UseDynamicObjectClassForAnonymousTypes { get; set; } = false;
///
- /// Gets or sets a value indicating whether the EntityFramwwork version supports evaluating GroupBy at database level.
+ /// Gets or sets a value indicating whether the EntityFramwwork version supports evaluating GroupBy at database level. Default value is false.
/// See https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.1#linq-groupby-translation
///
- public bool EvaluateGroupByAtDatabase { get; set; }
+ public bool EvaluateGroupByAtDatabase { get; set; } = false;
///
/// Use Parameterized Names in generated dynamic SQL query. Default set to true.
@@ -92,8 +93,13 @@ public IExpressionPromoter ExpressionPromoter
public bool UseParameterizedNamesInDynamicQuery { get; set; } = false;
///
- /// Allows the New() keyword to evaluate any available Type.
+ /// Allows the New() keyword to evaluate any available Type. Default value is false.
///
public bool AllowNewToEvaluateAnyType { get; set; } = false;
+
+ ///
+ /// Renames the (Typed)ParameterExpression empty Name to a the correct supplied name from `it`. Default value is false.
+ ///
+ public bool RenameParameterExpression { get; set; } = false;
}
}
diff --git a/src/System.Linq.Dynamic.Core/Properties/debugSettings.json b/src/System.Linq.Dynamic.Core/Properties/debugSettings.json
deleted file mode 100644
index a44fad34..00000000
--- a/src/System.Linq.Dynamic.Core/Properties/debugSettings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Profiles": []
-}
\ No newline at end of file
diff --git a/src/System.Linq.Dynamic.Core/Util/ParameterExpressionRenamer.cs b/src/System.Linq.Dynamic.Core/Util/ParameterExpressionRenamer.cs
new file mode 100644
index 00000000..960baa12
--- /dev/null
+++ b/src/System.Linq.Dynamic.Core/Util/ParameterExpressionRenamer.cs
@@ -0,0 +1,74 @@
+using JetBrains.Annotations;
+using System.Linq.Dynamic.Core.Validation;
+using System.Linq.Expressions;
+
+namespace System.Linq.Dynamic.Core.Util
+{
+ ///
+ /// Renames a single (Typed)ParameterExpression in an Expression.
+ ///
+ ///
+ internal class ParameterExpressionRenamer : ExpressionVisitor
+ {
+ private readonly string _newName;
+ private readonly string _oldName;
+
+ private ParameterExpression _parameterExpression;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The new name (the oldName is assumed to be "").
+ public ParameterExpressionRenamer([NotNull] string newName) : this("", newName)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The old name.
+ /// The new name.
+ public ParameterExpressionRenamer([NotNull] string oldName, [NotNull] string newName)
+ {
+ Check.NotNull(oldName, nameof(oldName));
+ Check.NotEmpty(newName, nameof(newName));
+
+ _oldName = oldName;
+ _newName = newName;
+ }
+
+ ///
+ /// Renames a single (Typed)ParameterExpression from specified expression.
+ ///
+ /// The expression.
+ /// The new generated (Typed)ParameterExpression.
+ /// Renamed Expression
+ public Expression Rename(Expression expression, out ParameterExpression parameterExpression)
+ {
+ var visitedExpression = Visit(expression);
+
+ parameterExpression = _parameterExpression;
+
+ return visitedExpression;
+ }
+
+ ///
+ protected override Expression VisitParameter(ParameterExpression node)
+ {
+ if (string.Equals(_oldName, node.Name, StringComparison.Ordinal))
+ {
+ if (_parameterExpression == null)
+ {
+ _parameterExpression = ParameterExpressionHelper.CreateParameterExpression(node.Type, _newName);
+ }
+
+ return _parameterExpression;
+ // throw new InvalidOperationException($"The {nameof(ParameterExpressionRenamer)} can only rename 1 (Typed)ParameterExpression in an Expression.");
+ }
+ else
+ {
+ return node;
+ }
+ }
+ }
+}
diff --git a/test/EntityFramework.DynamicLinq.Tests.net452/EntityFramework.DynamicLinq.Tests.net452.csproj b/test/EntityFramework.DynamicLinq.Tests.net452/EntityFramework.DynamicLinq.Tests.net452.csproj
index 844be632..effb692b 100644
--- a/test/EntityFramework.DynamicLinq.Tests.net452/EntityFramework.DynamicLinq.Tests.net452.csproj
+++ b/test/EntityFramework.DynamicLinq.Tests.net452/EntityFramework.DynamicLinq.Tests.net452.csproj
@@ -202,9 +202,6 @@
Entities\User.cs
-
- ExpressionPromoterTests.cs
-
ExpressionTests.cs
@@ -354,6 +351,7 @@
+
diff --git a/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj b/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj
index 6eee6e5f..83af2fb0 100644
--- a/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj
+++ b/test/EntityFramework.DynamicLinq.Tests/EntityFramework.DynamicLinq.Tests.csproj
@@ -23,6 +23,7 @@
+
diff --git a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
index 851a540d..64a970d9 100644
--- a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
@@ -23,6 +23,7 @@ private class ComplexParseLambda1Result
{
public int? Age;
public int TotalIncome;
+ public string Name;
}
[DynamicLinqType]
@@ -114,7 +115,7 @@ public Type ResolveType(string typeName)
}
[Fact]
- public void ParseLambda_UseParameterizedNamesInDynamicQuery_true()
+ public void DynamicExpressionParser_ParseLambda_UseParameterizedNamesInDynamicQuery_true()
{
// Assign
var config = new ParsingConfig
@@ -134,7 +135,7 @@ public void ParseLambda_UseParameterizedNamesInDynamicQuery_true()
}
[Fact]
- public void ParseLambda_UseParameterizedNamesInDynamicQuery_false()
+ public void DynamicExpressionParser_ParseLambda_UseParameterizedNamesInDynamicQuery_false()
{
// Assign
var config = new ParsingConfig
@@ -153,7 +154,7 @@ public void ParseLambda_UseParameterizedNamesInDynamicQuery_false()
}
[Fact]
- public void ParseLambda_ToList()
+ public void DynamicExpressionParser_ParseLambda_ToList()
{
// Arrange
var testList = User.GenerateSampleModels(51);
@@ -174,7 +175,7 @@ public void ParseLambda_ToList()
}
[Fact]
- public void ParseLambda_Complex_1()
+ public void DynamicExpressionParser_ParseLambda_Complex_1()
{
// Arrange
var testList = User.GenerateSampleModels(51);
@@ -204,7 +205,7 @@ public void ParseLambda_Complex_1()
}
[Fact]
- public void ParseLambda_Complex_2()
+ public void DynamicExpressionParser_ParseLambda_Complex_2()
{
// Arrange
var testList = User.GenerateSampleModels(51);
@@ -229,7 +230,7 @@ public void ParseLambda_Complex_2()
}
[Fact]
- public void ParseLambda_Complex_3()
+ public void DynamicExpressionParser_ParseLambda_Complex_3()
{
var config = new ParsingConfig
{
@@ -264,7 +265,7 @@ public void ParseLambda_Complex_3()
}
[Fact]
- public void ParseLambda_Select_1()
+ public void DynamicExpressionParser_ParseLambda_Select_1()
{
// Arrange
var testList = User.GenerateSampleModels(51);
@@ -286,7 +287,7 @@ public void ParseLambda_Select_1()
}
[Fact]
- public void ParseLambda_Select_2()
+ public void DynamicExpressionParser_ParseLambda_Select_2()
{
// Arrange
var testList = User.GenerateSampleModels(5);
@@ -309,7 +310,7 @@ public void ParseLambda_Select_2()
// https://github.com/StefH/System.Linq.Dynamic.Core/issues/58
[Fact]
- public void ParseLambda_4_Issue58()
+ public void DynamicExpressionParser_ParseLambda_4_Issue58()
{
var expressionParams = new[]
{
@@ -328,7 +329,7 @@ public void ParseLambda_4_Issue58()
}
[Fact]
- public void ParseLambda_DuplicateParameterNames_ThrowsException()
+ public void DynamicExpressionParser_ParseLambda_DuplicateParameterNames_ThrowsException()
{
// Arrange
var parameters = new[]
@@ -344,7 +345,7 @@ public void ParseLambda_DuplicateParameterNames_ThrowsException()
}
[Fact]
- public void ParseLambda_EmptyParameterList()
+ public void DynamicExpressionParser_ParseLambda_EmptyParameterList()
{
// Arrange
var pEmpty = new ParameterExpression[] { };
@@ -358,7 +359,7 @@ public void ParseLambda_EmptyParameterList()
}
[Fact]
- public void ParseLambda_ParameterName()
+ public void DynamicExpressionParser_ParseLambda_ParameterName()
{
// Arrange
var parameters = new[]
@@ -376,7 +377,7 @@ public void ParseLambda_ParameterName()
}
[Fact]
- public void ParseLambda_ParameterName_Empty()
+ public void DynamicExpressionParser_ParseLambda_ParameterName_Empty()
{
// Arrange
var parameters = new[]
@@ -392,7 +393,7 @@ public void ParseLambda_ParameterName_Empty()
}
[Fact]
- public void ParseLambda_ParameterName_Null()
+ public void DynamicExpressionParser_ParseLambda_ParameterName_Null()
{
// Arrange
var parameters = new[]
@@ -408,7 +409,7 @@ public void ParseLambda_ParameterName_Null()
}
[Fact]
- public void ParseLambda_ParameterExpressionMethodCall_ReturnsIntExpression()
+ public void DynamicExpressionParser_ParseLambda_ParameterExpressionMethodCall_ReturnsIntExpression()
{
var expression = DynamicExpressionParser.ParseLambda(true,
new[] { Expression.Parameter(typeof(int), "x") },
@@ -418,7 +419,7 @@ public void ParseLambda_ParameterExpressionMethodCall_ReturnsIntExpression()
}
[Fact]
- public void ParseLambda_RealNumbers()
+ public void DynamicExpressionParser_ParseLambda_RealNumbers()
{
var parameters = new ParameterExpression[0];
@@ -435,7 +436,7 @@ public void ParseLambda_RealNumbers()
}
[Fact]
- public void ParseLambda_StringLiteral_ReturnsBooleanLambdaExpression()
+ public void DynamicExpressionParser_ParseLambda_StringLiteral_ReturnsBooleanLambdaExpression()
{
var expression = DynamicExpressionParser.ParseLambda(
new[] { Expression.Parameter(typeof(string), "Property1") }, typeof(bool), "Property1 == \"test\"");
@@ -443,7 +444,7 @@ public void ParseLambda_StringLiteral_ReturnsBooleanLambdaExpression()
}
[Fact]
- public void ParseLambda_StringLiteralEmpty_ReturnsBooleanLambdaExpression()
+ public void DynamicExpressionParser_ParseLambda_StringLiteralEmpty_ReturnsBooleanLambdaExpression()
{
var expression = DynamicExpressionParser.ParseLambda(
new[] { Expression.Parameter(typeof(string), "Property1") }, typeof(bool), "Property1 == \"\"");
@@ -451,7 +452,7 @@ public void ParseLambda_StringLiteralEmpty_ReturnsBooleanLambdaExpression()
}
[Fact]
- public void ParseLambda_Config_StringLiteralEmpty_ReturnsBooleanLambdaExpression()
+ public void DynamicExpressionParser_ParseLambda_Config_StringLiteralEmpty_ReturnsBooleanLambdaExpression()
{
var config = new ParsingConfig();
var expression = DynamicExpressionParser.ParseLambda(
@@ -460,7 +461,7 @@ public void ParseLambda_Config_StringLiteralEmpty_ReturnsBooleanLambdaExpression
}
[Fact]
- public void ParseLambda_StringLiteralEmbeddedQuote_ReturnsBooleanLambdaExpression()
+ public void DynamicExpressionParser_ParseLambda_StringLiteralEmbeddedQuote_ReturnsBooleanLambdaExpression()
{
string expectedRightValue = "\"test \\\"string\"";
@@ -476,7 +477,7 @@ public void ParseLambda_StringLiteralEmbeddedQuote_ReturnsBooleanLambdaExpressio
}
[Fact]
- public void ParseLambda_StringLiteralStartEmbeddedQuote_ReturnsBooleanLambdaExpression()
+ public void DynamicExpressionParser_ParseLambda_StringLiteralStartEmbeddedQuote_ReturnsBooleanLambdaExpression()
{
// Assign
string expectedRightValue = "\"\\\"test\"";
@@ -492,7 +493,7 @@ public void ParseLambda_StringLiteralStartEmbeddedQuote_ReturnsBooleanLambdaExpr
}
[Fact]
- public void ParseLambda_StringLiteral_MissingClosingQuote()
+ public void DynamicExpressionParser_ParseLambda_StringLiteral_MissingClosingQuote()
{
string expectedRightValue = "\"test\\\"";
@@ -503,7 +504,7 @@ public void ParseLambda_StringLiteral_MissingClosingQuote()
}
[Fact]
- public void ParseLambda_StringLiteralEscapedBackslash_ReturnsBooleanLambdaExpression()
+ public void DynamicExpressionParser_ParseLambda_StringLiteralEscapedBackslash_ReturnsBooleanLambdaExpression()
{
// Assign
string expectedRightValue = "\"test\\string\"";
@@ -520,7 +521,7 @@ public void ParseLambda_StringLiteralEscapedBackslash_ReturnsBooleanLambdaExpres
}
[Fact]
- public void ParseLambda_TupleToStringMethodCall_ReturnsStringLambdaExpression()
+ public void DynamicExpressionParser_ParseLambda_TupleToStringMethodCall_ReturnsStringLambdaExpression()
{
var expression = DynamicExpressionParser.ParseLambda(
typeof(Tuple),
@@ -530,14 +531,14 @@ public void ParseLambda_TupleToStringMethodCall_ReturnsStringLambdaExpression()
}
[Fact]
- public void ParseLambda_IllegalMethodCall_ThrowsException()
+ public void DynamicExpressionParser_ParseLambda_IllegalMethodCall_ThrowsException()
{
Check.ThatCode(() => { DynamicExpressionParser.ParseLambda(typeof(IO.FileStream), null, "it.Close()"); })
.Throws().WithMessage("Methods on type 'Stream' are not accessible");
}
[Fact]
- public void ParseLambda_CustomMethod()
+ public void DynamicExpressionParser_ParseLambda_CustomMethod()
{
// Assign
var config = new ParsingConfig
@@ -560,7 +561,7 @@ public void ParseLambda_CustomMethod()
}
[Fact]
- public void ParseLambda_With_InnerStringLiteral()
+ public void DynamicExpressionParser_ParseLambda_With_InnerStringLiteral()
{
var originalTrueValue = "simple + \"quoted\"";
var doubleQuotedTrueValue = "simple + \"\"quoted\"\"";
@@ -572,7 +573,7 @@ public void ParseLambda_With_InnerStringLiteral()
}
[Fact]
- public void ParseLambda_With_Guid_Equals_Null()
+ public void DynamicExpressionParser_ParseLambda_With_Guid_Equals_Null()
{
// Arrange
var user = new User();
@@ -593,7 +594,7 @@ public void ParseLambda_With_Guid_Equals_Null()
}
[Fact]
- public void ParseLambda_With_Null_Equals_Guid()
+ public void DynamicExpressionParser_ParseLambda_With_Null_Equals_Guid()
{
// Arrange
var user = new User();
@@ -614,7 +615,7 @@ public void ParseLambda_With_Null_Equals_Guid()
}
[Fact]
- public void ParseLambda_With_Guid_Equals_String()
+ public void DynamicExpressionParser_ParseLambda_With_Guid_Equals_String()
{
// Arrange
Guid someId = Guid.NewGuid();
@@ -638,7 +639,7 @@ public void ParseLambda_With_Guid_Equals_String()
}
[Fact]
- public void ParseLambda_With_Concat_String_CustomType()
+ public void DynamicExpressionParser_ParseLambda_With_Concat_String_CustomType()
{
// Arrange
string name = "name1";
@@ -662,7 +663,7 @@ public void ParseLambda_With_Concat_String_CustomType()
}
[Fact]
- public void ParseLambda_With_Concat_CustomType_String()
+ public void DynamicExpressionParser_ParseLambda_With_Concat_CustomType_String()
{
// Arrange
string name = "name1";
@@ -686,7 +687,7 @@ public void ParseLambda_With_Concat_CustomType_String()
}
[Fact]
- public void ParseLambda_Operator_Less_Greater_With_Guids()
+ public void DynamicExpressionParser_ParseLambda_Operator_Less_Greater_With_Guids()
{
var config = new ParsingConfig
{
@@ -713,5 +714,24 @@ public void ParseLambda_Operator_Less_Greater_With_Guids()
// Assert
Assert.Equal(anotherId, result);
}
+
+ [Theory]
+ [InlineData("c => c.Age == 8", "c => (c.Age == 8)")]
+ [InlineData("c => c.Name == \"test\"", "c => (c.Name == \"test\")")]
+ public void DynamicExpressionParser_ParseLambda_RenameParameterExpression(string expressionAsString, string expected)
+ {
+ // Arrange
+ var config = new ParsingConfig
+ {
+ RenameParameterExpression = true
+ };
+
+ // Act
+ var expression = DynamicExpressionParser.ParseLambda(config, true, expressionAsString);
+ string result = expression.ToString();
+
+ // Assert
+ Check.That(result).IsEqualTo(expected);
+ }
}
}
diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionHelperTests.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionHelperTests.cs
similarity index 96%
rename from test/System.Linq.Dynamic.Core.Tests/ExpressionHelperTests.cs
rename to test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionHelperTests.cs
index 17da8691..c29ef4c6 100644
--- a/test/System.Linq.Dynamic.Core.Tests/ExpressionHelperTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionHelperTests.cs
@@ -3,7 +3,7 @@
using NFluent;
using Xunit;
-namespace System.Linq.Dynamic.Core.Tests
+namespace System.Linq.Dynamic.Core.Parser.Tests
{
public class ExpressionHelperTests
{
diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionPromoterTests.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionPromoterTests.cs
similarity index 98%
rename from test/System.Linq.Dynamic.Core.Tests/ExpressionPromoterTests.cs
rename to test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionPromoterTests.cs
index ef6974b0..b08ddf76 100644
--- a/test/System.Linq.Dynamic.Core.Tests/ExpressionPromoterTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionPromoterTests.cs
@@ -5,7 +5,7 @@
using System.Linq.Expressions;
using Xunit;
-namespace System.Linq.Dynamic.Core.Tests
+namespace System.Linq.Dynamic.Core.Parser.Tests
{
public class ExpressionPromoterTests
{
diff --git a/test/System.Linq.Dynamic.Core.Tests/TypeHelperTests.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/TypeHelperTests.cs
similarity index 96%
rename from test/System.Linq.Dynamic.Core.Tests/TypeHelperTests.cs
rename to test/System.Linq.Dynamic.Core.Tests/Parser/TypeHelperTests.cs
index df2b921f..e473f8dd 100644
--- a/test/System.Linq.Dynamic.Core.Tests/TypeHelperTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/TypeHelperTests.cs
@@ -2,7 +2,7 @@
using System.Linq.Dynamic.Core.Parser;
using Xunit;
-namespace System.Linq.Dynamic.Core.Tests
+namespace System.Linq.Dynamic.Core.Tests.Parser
{
public class TypeHelperTests
{
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
index 307dfbd4..7785d83b 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
@@ -16,6 +16,43 @@ namespace System.Linq.Dynamic.Core.Tests
{
public partial class QueryableTests
{
+ public class Example
+ {
+ public DateTime Time { get; set; }
+ public DayOfWeek? DOWNull { get; set; }
+ public DayOfWeek DOW { get; set; }
+ public int Sec { get; set; }
+ public int? SecNull { get; set; }
+
+ public class NestedDto
+ {
+ public string Name { get; set; }
+
+ public class NestedDto2
+ {
+ public string Name2 { get; set; }
+ }
+ }
+ }
+
+ public class ExampleWithConstructor
+ {
+ public DateTime Time { get; set; }
+ public DayOfWeek? DOWNull { get; set; }
+ public DayOfWeek DOW { get; set; }
+ public int Sec { get; set; }
+ public int? SecNull { get; set; }
+
+ public ExampleWithConstructor(DateTime t, DayOfWeek? dn, DayOfWeek d, int s, int? sn)
+ {
+ Time = t;
+ DOWNull = dn;
+ DOW = d;
+ Sec = s;
+ SecNull = sn;
+ }
+ }
+
///
/// Cannot work with property which in base class. https://github.com/StefH/System.Linq.Dynamic.Core/issues/23
///
@@ -190,43 +227,6 @@ public void Select_Dynamic_IntoType()
Assert.Equal(testList.Select(x => x.Profile).Cast