コード例 #1
0
ファイル: SelectorExpression.cs プロジェクト: melnx/Bermuda
        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);
        }
コード例 #2
0
ファイル: SelectorExpression.cs プロジェクト: melnx/Bermuda
        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);
        }