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 = QueryableHelpers.GetTypeOfEnumerable(memberExpression.Type, false), Parent = parent, Name = pp }; Pieces.Add(current); // for next iteration. param = Expression.Parameter(current.IsGenericEnumerable ? current.EnumerableType : current.Type); parent = current; }); }
private Expression CheckNullOnFirstGroup(ExpressionParserPieceGroup group, Expression currentExpression) { var path = string.Join(".", group.Pieces.Select(t => t.Name)); var whereExpression = QueryableHelpers.CreateConditionExpression(group.Parameter.Type, path, ConditionOperators.NotEqual, null, QueryConvertStrategy.ConvertConstantToComparedPropertyOrField, parameter: group.Parameter, nullChecking: true); var whereBodyExpression = (whereExpression as LambdaExpression).Body; whereBodyExpression = Expression.Not(whereBodyExpression); var nullType = currentExpression.Type; Expression ifTrueExpression = null; if (QueryableHelpers.IsGenericEnumerable(nullType)) { var enumerableType = QueryableHelpers.GetTypeOfEnumerable(nullType, true); var listType = typeof(List <>).MakeGenericType(enumerableType); ifTrueExpression = Expression.New(listType); } else { ifTrueExpression = Expression.Default(nullType); } return(Expression.Condition(whereBodyExpression, ifTrueExpression, currentExpression, currentExpression.Type)); }
public void TestInheritanceOfListAsGenericEnumerableType() { var shouldBeTrue = QueryableHelpers.IsGenericEnumerable(typeof(ListOfFoo)); Assert.IsTrue(shouldBeTrue); var type = QueryableHelpers.GetTypeOfEnumerable(typeof(ListOfFoo), true); Assert.IsTrue(type == typeof(Foo)); }
public void Resolve() { Result = null; // parse the expression. if (!Parser.IsParsed) { Parser.Parse(); } // group the piece by common parameters var groups = Parser.GroupBySharedParameters(); Expression currentExpression = null; foreach (var group in groups.Reversed()) { var isLastGroup = groups.IndexOf(group) == groups.Count - 1; if (currentExpression == null) { var groupExpression = CompileGroup(group, NullChecking); var groupExpressionLambda = Expression.Lambda(groupExpression, group.Parameter); if (group.Parent == null) { currentExpression = groupExpression; if (NullChecking != false) { currentExpression = CheckNullOnFirstGroup(group, currentExpression); } currentExpression = Expression.Lambda(currentExpression, group.Parameter); continue; } var parent = group.Parent; var parentExpression = CompileGroup(parent, NullChecking); // check null with where. var isSelectMany = CollectionHandling == SelectCollectionHandling.Flatten && QueryableHelpers.IsGenericEnumerable(groupExpression); if (NullChecking != false) { parentExpression = CheckNullOnEnumerableParent(group, parent, parentExpression, isLastGroup && !isSelectMany); } // the select expression. if (isSelectMany) { var selectType = parent.GroupEnumerableType(); var groupExpressionEnumerableType = QueryableHelpers.GetTypeOfEnumerable(groupExpression.Type, true); var selectExpression = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { selectType, groupExpressionEnumerableType }, parentExpression, groupExpressionLambda); currentExpression = selectExpression; } else { var selectType = parent.GroupEnumerableType(); var selectExpression = Expression.Call(typeof(Enumerable), "Select", new Type[] { selectType, groupExpression.Type }, parentExpression, groupExpressionLambda); currentExpression = selectExpression; } } else { if (group.Parent == null) { if (NullChecking != false) { currentExpression = CheckNullOnFirstGroup(group, currentExpression); } currentExpression = Expression.Lambda(currentExpression, group.Parameter); continue; } var parent = group.Parent; var parentExpression = CompileGroup(parent, NullChecking); var selectType = parent.GroupEnumerableType(); bool isSelectMany = CollectionHandling == SelectCollectionHandling.Flatten && QueryableHelpers.IsGenericEnumerable(currentExpression); if (NullChecking != false) { parentExpression = CheckNullOnEnumerableParent(group, parent, parentExpression, isLastGroup && !isSelectMany); } if (isSelectMany) { var currentExpressionEnumerableType = QueryableHelpers.GetTypeOfEnumerable(currentExpression.Type, true); var currentExpressionLambda = Expression.Lambda(currentExpression, group.Parameter); currentExpression = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { selectType, currentExpressionEnumerableType }, parentExpression, currentExpressionLambda); } else { var currentExpressionLambda = Expression.Lambda(currentExpression, group.Parameter); currentExpression = Expression.Call(typeof(Enumerable), "Select", new Type[] { selectType, currentExpression.Type }, parentExpression, currentExpressionLambda); } } } Result = currentExpression; }