using PoweredSoft.DynamicLinq.Helpers; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace PoweredSoft.DynamicLinq.Parser { public class ExpressionParser { public ParameterExpression Parameter { get; protected set; } public string Path { get; set; } public List Pieces { get; set; } = new List(); public ExpressionParser(Type type, string path) : this(Expression.Parameter(type), path) { } public ExpressionParser(ParameterExpression parameter, string path) { Parameter = parameter; Path = path; } public static ExpressionParserPiece GetFirstEnumerableParent(ExpressionParserPiece piece) { if (piece.Parent == null) return null; if (piece.Parent.IsGenericEnumerable) return piece.Parent; return GetFirstEnumerableParent(piece.Parent); } public void Parse() { Pieces.Clear(); var pathPieces = Path.Split('.').ToList(); var param = Parameter; ExpressionParserPiece parent = null; pathPieces.ForEach(pp => { var memberExpression = Expression.PropertyOrField(param, pp); var current = new ExpressionParserPiece { Type = memberExpression.Type, IsGenericEnumerable = QueryableHelpers.IsGenericEnumerable(memberExpression), EnumerableType = memberExpression.Type.GenericTypeArguments.FirstOrDefault(), Parent = parent, Name = pp }; Pieces.Add(current); // for next iteration. param = Expression.Parameter(current.IsGenericEnumerable ? current.EnumerableType : current.Type); parent = current; }); } private ExpressionParserPieceGroup CreateAndAddGroup(List groups, ParameterExpression parameter) { var group = new ExpressionParserPieceGroup(); group.ParameterExpression = parameter; groups.Add(group); return group; } public List GroupBySharedParameters() { var groups = new List(); var group = CreateAndAddGroup(groups, Parameter); Pieces.ForEach(piece => { group.Pieces.Add(piece); if (piece.IsGenericEnumerable) group = CreateAndAddGroup(groups, Expression.Parameter(piece.EnumerableType)); }); return groups; } } }