private static Expression CreateCollectionContainsExpression(Expression rightExpression, ParameterExpression xParam, Expression leftExpression) { var itemType = ReduceExpressionGeneration.GetTypeOfEnumerable(leftExpression.Type); Expression rhs = null; if (ReduceExpressionGeneration.IsTupleType(itemType)) { var anyMethodInfosGeneric = typeof(Enumerable).GetMethods().Where(x => x.Name == "Any" && x.GetParameters().Length == 2); var anyMethodInfoGeneric = anyMethodInfosGeneric.FirstOrDefault(); var anyMethodInfo = anyMethodInfoGeneric.MakeGenericMethod(itemType); var item2Info = itemType.GetProperty("Item2"); var itemParam = Expression.Parameter(itemType, "tpl"); var item2Access = Expression.MakeMemberAccess(itemParam, item2Info); var equalsExpr = Expression.Equal(item2Access, rightExpression); var lambda = Expression.Lambda ( delegateType: typeof(Func <,>).MakeGenericType(itemType, typeof(bool)), parameters: itemParam, body: equalsExpr ); rhs = Expression.Call ( method: anyMethodInfo, arg0: leftExpression, arg1: lambda ); } else { var containsMethodInfosGeneric = typeof(Enumerable).GetMethods().Where(x => x.Name == "Contains" && x.GetParameters().Length == 2); var containsMethodInfoGeneric = containsMethodInfosGeneric.FirstOrDefault(); var containsMethodInfo = containsMethodInfoGeneric.MakeGenericMethod(itemType); //var actualValue = Convert.ChangeType(Child, itemType); rhs = Expression.Call ( method: containsMethodInfo, arg0: leftExpression, arg1: rightExpression ); //var targetMemberAccess = Expression.MakeMemberAccess(xParam, targetField); } //return rhs; var result = Expression.AndAlso ( Expression.ReferenceNotEqual(leftExpression, Expression.Constant(null)), rhs ); return(result); }
public override Expression CreateExpression(object context) { //return null; //var literalRight = Right as LiteralExpression; //var valueRight = Right as ValueExpression; //var dimensionRight = Right as DimensionExpression; //var literalLeft = Left as LiteralExpression; //var valueLeft = Left as ValueExpression; //var dimensionLeft = Left as DimensionExpression; var leftExpression = Left == null ? null : Left.CreateExpression(new DimensionCreateExpressionParameter { QuoteUnknownIdentifiers = Right == null, Left = Left, Right = Right }); var rightExpression = Right == null ? null : Right.CreateExpression(new DimensionCreateExpressionParameter { QuoteUnknownIdentifiers = true, Left = Left, Right = Right }); var asLeftRange = leftExpression as NewArrayExpression; var asRightRange = rightExpression as NewArrayExpression; if (asLeftRange != null) { throw new BermudaExpressionGenerationException("Ranges are only supported on the right hand side"); } if (asRightRange == null && leftExpression != null && rightExpression != null && leftExpression.Type != rightExpression.Type) { var asLeftLiteral = leftExpression as ConstantExpression; Expression asLeftDimension = leftExpression; var asRightLiteral = rightExpression as ConstantExpression; Expression asRightDimension = rightExpression; //if (asLeftDimension == null) asLeftDimension = leftExpression as MethodCallExpression; //if (asRightDimension == null) asRightDimension = asRightDimension as MethodCallExpression; try { if (asLeftLiteral == null && asRightLiteral == null) { rightExpression = Expression.Convert(rightExpression, leftExpression.Type); } else if (asLeftDimension != null && asRightLiteral != null) { var targetType = leftExpression.Type; if (ReduceExpressionGeneration.IsCollectionType(targetType)) { targetType = ReduceExpressionGeneration.GetTypeOfEnumerable(targetType); } if (ReduceExpressionGeneration.IsTupleType(targetType)) { targetType = targetType.GetGenericArguments().Last(); } long num; if (targetType == typeof(long) && asRightLiteral.Value is string && !long.TryParse(asRightLiteral.Value as string, out num)) { var lookupKey = leftExpression.ToString().Split('.').LastOrDefault(); if (!string.IsNullOrWhiteSpace(lookupKey)) { num = GetLookup(lookupKey, asRightLiteral.Value as string); } } rightExpression = Expression.Constant(Convert.ChangeType(asRightLiteral.Value, targetType)); } else if (asLeftLiteral != null && asRightDimension != null) { var targetType = rightExpression.Type; if (ReduceExpressionGeneration.IsCollectionType(targetType)) { targetType = ReduceExpressionGeneration.GetTypeOfEnumerable(targetType); } if (!ReduceExpressionGeneration.IsTupleType(targetType)) { targetType = targetType.GetGenericArguments().Last(); } leftExpression = Expression.Constant(Convert.ChangeType(asLeftLiteral.Value, targetType)); } else if (asLeftLiteral != null && asRightLiteral != null) { leftExpression = Expression.Constant(Convert.ChangeType(asLeftLiteral.Value, rightExpression.Type)); } else { throw new BermudaExpressionGenerationException("Not supposed to happen"); } } catch (Exception ex) { if (ex is BermudaExpressionGenerationException) { throw ex; } //throw new BermudaExpressionGenerationException("Failed to convert: " + ex.Message); Root.AddWarning(ex.ToString()); return(null); } } //if (literalRight == null && valueRight == null) //{ // throw new Exception("The selector must specify an expression child or a literal child"); //} //object rightValue = literalRight != null ? (object)literalRight.Value : (object)valueRight.Value; //object leftValue = literalLeft != null ? (object)literalLeft.Value : (object)valueLeft.Value; var getExpression = (GetExpression)Root; Type elementType = Root.ElementType; var xParam = Expression.Parameter(elementType, "x"); //freeform strings inside the query switch (NodeType) { case SelectorTypes.Unspecified: { if (Parent is DimensionExpression) { return(rightExpression); } if (Right != null) { var name = Right.ToString(); var boolField = ReduceExpressionGeneration.GetField(elementType, name, false); if (boolField != null) { Expression boolFieldAccess = Expression.MakeMemberAccess(xParam, boolField); return(boolFieldAccess); } //var isTrue = Expression.Equal(boolFieldAccess, Expression.Constant(true)); } return(CreateUnspecifiedStringExpression(rightExpression, elementType, xParam)); } case SelectorTypes.Unknown: { if (leftExpression == null || rightExpression == null) { return(null); } switch (Modifier) { case ModifierTypes.Contains: return(CreateCollectionContainsExpression(rightExpression, xParam, leftExpression)); case ModifierTypes.In: return(CreateInExpression(rightExpression, xParam, leftExpression)); case ModifierTypes.Like: case ModifierTypes.Colon: if (leftExpression.Type == typeof(string)) { return(CreateStringFieldContainsExpression(leftExpression, rightExpression)); } else if (ReduceExpressionGeneration.IsCollectionType(leftExpression.Type)) { goto case ModifierTypes.Contains; } else { if (asRightRange != null) { goto case ModifierTypes.InRange; } else { goto case ModifierTypes.Equals; } } case ModifierTypes.InRange: return(CreateInRangeExpression(leftExpression, asRightRange)); case ModifierTypes.Equals: return(Expression.Equal(leftExpression, rightExpression)); case ModifierTypes.GreaterThan: if (asRightRange != null) { goto case ModifierTypes.InRange; } return(Expression.GreaterThan(leftExpression, rightExpression)); case ModifierTypes.LessThan: if (asRightRange != null) { goto case ModifierTypes.InRange; } return(Expression.LessThan(leftExpression, rightExpression)); case ModifierTypes.Add: return(Expression.Add(leftExpression, rightExpression)); case ModifierTypes.Subtract: return(Expression.Add(leftExpression, rightExpression)); case ModifierTypes.Multiply: return(Expression.Add(leftExpression, rightExpression)); case ModifierTypes.Divide: return(Expression.Add(leftExpression, rightExpression)); default: throw new BermudaExpressionGenerationException("Unsupported Operator " + Modifier + " for Operands " + leftExpression + " and " + rightExpression); } } } return(null); }