From 2f4c406503d6930fce5a8c61d7d4693c074b9972 Mon Sep 17 00:00:00 2001 From: David Lebee Date: Tue, 27 Mar 2018 19:06:04 -0500 Subject: [PATCH] fiou something that works finally. :) --- PoweredSoft.DynamicLinq.ConsoleApp/Program.cs | 72 +++++++++++++------ PoweredSoft.DynamicLinq/ExpressionPathPart.cs | 24 +++++-- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/PoweredSoft.DynamicLinq.ConsoleApp/Program.cs b/PoweredSoft.DynamicLinq.ConsoleApp/Program.cs index 6edf87f..825f100 100644 --- a/PoweredSoft.DynamicLinq.ConsoleApp/Program.cs +++ b/PoweredSoft.DynamicLinq.ConsoleApp/Program.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; namespace PoweredSoft.DynamicLinq.ConsoleApp { - public class Program + public class SelectExpression { static void Main(string[] args) { @@ -23,9 +23,11 @@ namespace PoweredSoft.DynamicLinq.ConsoleApp Ids = t.Posts.SelectMany(t2 => t2.Comments.Select(t3 => t3.CommentLikes)) }); - var expressionParser = new ExpressionParser(typeof(Author), "Posts.Comments.Post.Author"); + var expressionParser = new ExpressionParser(typeof(Author), "Posts.Comments.Id"); expressionParser.Parse(); - var result = expressionParser.Groups; + + var finalExpression = CreateSelectExpressionFromParsed(expressionParser, SelectCollectionHandling.Flatten, SelectNullHandling.LeaveAsIs); + } @@ -46,45 +48,75 @@ namespace PoweredSoft.DynamicLinq.ConsoleApp });*/ //var result = CreateSelectExpressionFromParts(parts, SelectCollectionHandling.Flatten, SelectNullHandling.New); - } + //} - public static Expression CreateSelectExpressionFromParts(List parts, + public static Expression CreateSelectExpressionFromParsed(ExpressionParser expressionParser, SelectCollectionHandling selectCollectionHandling = SelectCollectionHandling.LeaveAsIs, SelectNullHandling nullChecking = SelectNullHandling.LeaveAsIs) { Type nullHandlingRightType = null; Expression nullHandlingNullValue = null; + /* if (nullChecking != SelectNullHandling.LeaveAsIs) { nullHandlingRightType = parts.Last().PartExpression.Type; nullHandlingNullValue = nullChecking == SelectNullHandling.Default ? Expression.Default(nullHandlingRightType) as Expression : Expression.New(nullHandlingRightType) as Expression; - } + }*/ // reversed :) - var reversedCopy = parts.Select(t => t).ToList(); + var reversedCopy = expressionParser.Groups.Select(t => t).ToList(); reversedCopy.Reverse(); + MethodCallExpression lastSelectExpression = null; Expression ret = null; - reversedCopy.ForEach(t => + + foreach(var t in reversedCopy) { - if (t.IsParentGenericEnumerable()) + if (true == t.Parent?.LastPiece().IsGenericEnumerable()) { - var lambda = t.GetLambdaExpression(); - var parentGenericType = t.ParentGenericEnumerableType(); - if (selectCollectionHandling == SelectCollectionHandling.LeaveAsIs || !t.IsGenericEnumerable()) - ret = Expression.Call(typeof(Enumerable), "Select", new Type[] { parentGenericType, t.PartExpression.Type }, t.ParentExpression, lambda); + if (lastSelectExpression == null) + lastSelectExpression = CreateSelectExpression(t, selectCollectionHandling); else - ret = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { parentGenericType, t.GenericEnumerableType() }, t.ParentExpression, lambda); + lastSelectExpression = CreateSelectExpression(t, lastSelectExpression, selectCollectionHandling); } - else - { - ret = t.PartExpression; - } - }); - + } + + ret = lastSelectExpression; + return ret; + } + + public static MethodCallExpression CreateSelectExpression(ExpressionParameterGroup group, SelectCollectionHandling selectCollectionHandling) + { + MethodCallExpression ret = null; + var lambda = group.CreateLambda(); + var parentExpression = group.Parent.LastExpression(); + var isParentExpressionGenericEnumerable = QueryableHelpers.IsGenericEnumerable(parentExpression); + var parentExpressionGenericEnumerableType = isParentExpressionGenericEnumerable ? parentExpression.Type.GenericTypeArguments.First() : null; + var lastPiece = group.LastPiece(); + + if (selectCollectionHandling == SelectCollectionHandling.LeaveAsIs || !lastPiece.IsGenericEnumerable()) + ret = Expression.Call(typeof(Enumerable), "Select", new Type[] { parentExpressionGenericEnumerableType, lastPiece.Expression.Type }, parentExpression, lambda); + else + ret = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { parentExpressionGenericEnumerableType, lastPiece.GetGenericEnumerableType() }, parentExpression, lambda); + + return ret; + } + + public static MethodCallExpression CreateSelectExpression(ExpressionParameterGroup group, MethodCallExpression innerSelect, SelectCollectionHandling selectCollectionHandling) + { + var parent = group.Parent; + var parentLastPiece = parent.LastPiece(); + + MethodCallExpression ret = null; + var lambda = Expression.Lambda(innerSelect, group.Parameter); + if (selectCollectionHandling == SelectCollectionHandling.LeaveAsIs) + ret = Expression.Call(typeof(Enumerable), "Select", new Type[] { parentLastPiece.GetGenericEnumerableType(), innerSelect.Type }, parentLastPiece.Expression, lambda); + else + ret = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { parentLastPiece.GetGenericEnumerableType(), innerSelect.Type.GenericTypeArguments.First() }, parentLastPiece.Expression, lambda); + return ret; } diff --git a/PoweredSoft.DynamicLinq/ExpressionPathPart.cs b/PoweredSoft.DynamicLinq/ExpressionPathPart.cs index e72d8e5..af4f392 100644 --- a/PoweredSoft.DynamicLinq/ExpressionPathPart.cs +++ b/PoweredSoft.DynamicLinq/ExpressionPathPart.cs @@ -9,7 +9,7 @@ namespace PoweredSoft.DynamicLinq.Helpers { public ExpressionParameterGroup Parent { get; set; } public ParameterExpression Parameter { get; set; } - public List Parts { get; set; } = new List(); + public List Pieces { get; set; } = new List(); public ExpressionParameterGroup(ParameterExpression parameter) { @@ -18,7 +18,18 @@ namespace PoweredSoft.DynamicLinq.Helpers public void AddSubPart(ExpressionPiece expressionPart) { - Parts.Add(expressionPart); + Pieces.Add(expressionPart); + } + + public Expression LastExpression() => LastPiece().Expression; + + public ExpressionPiece LastPiece() => Pieces.Last(); + + public LambdaExpression CreateLambda() + { + var lastExpression = LastPiece().Expression; + var lambda = Expression.Lambda(lastExpression, Parameter); + return lambda; } } @@ -26,7 +37,7 @@ namespace PoweredSoft.DynamicLinq.Helpers { public ExpressionParameterGroup Parameter { get; set; } public ExpressionPiece Parent { get; set; } - public Expression Part { get; set; } + public Expression Expression { get; set; } public ExpressionPiece(ExpressionParameterGroup parameter, ExpressionPiece parent = null) { @@ -36,11 +47,11 @@ namespace PoweredSoft.DynamicLinq.Helpers public void Resolve(string piece) { - Part = Expression.PropertyOrField(Parent?.Part ?? Parameter.Parameter, piece); + Expression = Expression.PropertyOrField(Parent?.Expression ?? Parameter.Parameter, piece); } - public bool IsGenericEnumerable() => QueryableHelpers.IsGenericEnumerable(Part); - public Type GetGenericEnumerableType() => Part.Type.GenericTypeArguments.First(); + public bool IsGenericEnumerable() => QueryableHelpers.IsGenericEnumerable(Expression); + public Type GetGenericEnumerableType() => Expression.Type.GenericTypeArguments.First(); } public class ExpressionParser @@ -75,6 +86,7 @@ namespace PoweredSoft.DynamicLinq.Helpers var currentGroup = CreateAndAddParameterGroup(Parameter); ExpressionPiece parentPiece = null; + int step = 0; pieces.ForEach(piece => { var expressionPiece = new ExpressionPiece(currentGroup, parentPiece);