/// <summary>
        /// Gets a <see cref="BindingSignatureSupport"/> from an expression.
        /// </summary>
        /// <param name="left">The left.</param>
        /// <param name="structureBinder">The structure binder.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        private static BindingSignatureSupport GetBindingSupport(Expression left, AbstractQueryStructureBinder structureBinder)
        {
            Func <MethodCallExpression, BindingSignatureSupport>
            getMethodSupport = x => ExpressionHelper.IsMethod(x) ? structureBinder.IsSupportedMethod(x) : null;

            Func <MemberExpression, BindingSignatureSupport>
            getMemberSupport = x => ExpressionHelper.IsMember(x) ? structureBinder.IsSupportedMember(x) : null;

            var supportedNonDynamic = getMemberSupport.Invoke(left as MemberExpression) ?? getMethodSupport.Invoke(left as MethodCallExpression);

            if (supportedNonDynamic == null)
            {
                var unary = left as UnaryExpression;
                if (unary != null)
                {
                    var innerMethod = unary.Operand as MethodCallExpression;
                    if (innerMethod != null)
                    {
                        return(getMethodSupport.Invoke(innerMethod));
                    }
                }
            }

            return(supportedNonDynamic);
        }
        /// <summary>
        /// Determines whether the supplied <see cref="BinaryExpression"/> is convertible to a binary in the context of the featureset of
        /// the Rebel Framework-supported expression tree.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="structureBinder">The structure binder.</param>
        /// <returns><c>true</c> if [is convertible binary] [the specified expression]; otherwise, <c>false</c>.</returns>
        /// <remarks></remarks>
        public static bool IsConvertibleBinary(BinaryExpression expression, AbstractQueryStructureBinder structureBinder)
        {
            var left  = expression.Left;
            var right = expression.Right;

            BindingSignatureSupport bindingSignatureSupport = GetBindingSupport(left, structureBinder);

            return(bindingSignatureSupport != null && (ExpressionHelper.IsConstant(right) || right is UnaryExpression));
        }
 /// <summary>
 /// Gets a <see cref="FieldSelectorExpression"/> from an expression it the <paramref name="bindingSignatureSupport"/> identifies it as supported.
 /// </summary>
 /// <param name="left">The left.</param>
 /// <param name="structureBinder">The structure binder.</param>
 /// <param name="bindingSignatureSupport">The binding signature support.</param>
 /// <returns></returns>
 /// <remarks></remarks>
 public static FieldSelectorExpression GetFieldSelector(Expression left, AbstractQueryStructureBinder structureBinder, BindingSignatureSupport bindingSignatureSupport)
 {
     switch (bindingSignatureSupport.SignatureSupportType)
     {
     case SignatureSupportType.SupportedAsFieldName:
         if (ExpressionHelper.IsMember(left))
         {
             return(structureBinder.CreateFieldSelector(left as MemberExpression, bindingSignatureSupport));
         }
         else if (ExpressionHelper.IsMethod(left))
         {
             return(structureBinder.CreateFieldSelector(left as MethodCallExpression, bindingSignatureSupport));
         }
         break;
     }
     return(null);
 }
 private static SchemaSelectorExpression GetSchemaSelector(Expression left, AbstractQueryStructureBinder structureBinder, BindingSignatureSupport bindingSignatureSupport)
 {
     switch (bindingSignatureSupport.SignatureSupportType)
     {
     case SignatureSupportType.SupportedAsSchemaAlias:
         if (ExpressionHelper.IsMember(left))
         {
             return(structureBinder.CreateSchemaSelector(left as MemberExpression, bindingSignatureSupport));
         }
         else if (ExpressionHelper.IsMethod(left))
         {
             return(structureBinder.CreateSchemaSelector(left as MethodCallExpression, bindingSignatureSupport));
         }
         break;
     }
     return(null);
 }
        public static FieldSelectorExpression GetFieldSelector(Expression left, AbstractQueryStructureBinder structureBinder)
        {
            var signatureSupport = GetBindingSupport(left, structureBinder);

            return(GetFieldSelector(left, structureBinder, signatureSupport));
        }
        /// <summary>
        /// Converts a <see cref="BinaryExpression"/> to a field predicate expression, if supported and convertible.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="structureBinder">The structure binder.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static Expression ConvertToFieldPredicate(BinaryExpression expression, AbstractQueryStructureBinder structureBinder)
        {
            if (IsConvertibleBinary(expression, structureBinder))
            {
                var left = expression.Left;

                // Check if the left had side is a Unary wrapping a DynamicMemberMetadata call just to get the type right
                var unaryLeft = left as UnaryExpression;
                if (unaryLeft != null)
                {
                    var methodLeft = unaryLeft.Operand as MethodCallExpression;
                    if (methodLeft != null && methodLeft.Method == DynamicMemberMetadata.GetMemberMethod)
                    {
                        left = methodLeft;
                    }
                }

                // First assume that the right hand side of the binary is a constant
                ConstantExpression right = expression.Right as ConstantExpression;

                // If it's not, it might be a unary (e.g. "convert value to object" if it's from DynamicMemberMetadata)
                if (right == null)
                {
                    var unary = expression.Right as UnaryExpression;
                    if (unary != null)
                    {
                        // If it was a unary, ignore the operator and just go for the operand (the value)
                        right = unary.Operand as ConstantExpression;
                    }
                }

                BindingSignatureSupport leftBindingSignatureSupport = GetBindingSupport(left, structureBinder);

                // Update the ValuePredicateType based on the expression which might reference an operator or a NodeType of NotEqual etc.
                UpdateValuePredicateType(leftBindingSignatureSupport, expression);

                switch (leftBindingSignatureSupport.SignatureSupportType)
                {
                case SignatureSupportType.SupportedAsFieldName:
                    var selectorExpression = GetFieldSelector(left, structureBinder, leftBindingSignatureSupport);
                    return(new FieldPredicateExpression(selectorExpression, new FieldValueExpression(leftBindingSignatureSupport.NodeType, right.Value)));

                case SignatureSupportType.SupportedAsFieldValue:
                    var methodCallExpression = ((MethodCallExpression)left);
                    if (ExpressionHelper.IsMethod(left))
                    {
                        var fieldValueExpression = structureBinder
                                                   .CreateFieldValueExpression(methodCallExpression, leftBindingSignatureSupport);

                        var objectOfMethod = methodCallExpression.Object;
                        var bindingSupportForMethodObject = GetBindingSupport(objectOfMethod, structureBinder);
                        var fieldSelector = GetFieldSelector(objectOfMethod, structureBinder, bindingSupportForMethodObject);

                        return(new FieldPredicateExpression(fieldSelector, fieldValueExpression));
                    }
                    break;

                case SignatureSupportType.SupportedAsSchemaAlias:
                    var schemaSelectorExpression = GetSchemaSelector(left, structureBinder, leftBindingSignatureSupport);
                    return
                        (new SchemaPredicateExpression(
                             new SchemaSelectorExpression(schemaSelectorExpression.Name),
                             new SchemaValueExpression(leftBindingSignatureSupport.NodeType, right.Value)));
                }
            }

            return(expression);
        }
示例#7
0
        /// <summary>
        /// Creates a new <see cref="QueryModelVisitor"/>, and returns the result of running <see cref="QueryModelVisitor.VisitAndGenerateQueryDescription"/> on the
        /// supplied <paramref name="queryModel"/>.
        /// </summary>
        /// <param name="queryModel">The query model.</param>
        /// <param name="structureBinder">The structure binder.</param>
        /// <param name="treeVisitor">The tree visitor.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static QueryDescription FromQueryModel(Remotion.Linq.QueryModel queryModel, AbstractQueryStructureBinder structureBinder, AbstractExpressionTreeVisitor treeVisitor)
        {
            var elrmv = new QueryModelVisitor(structureBinder, treeVisitor);

            return(elrmv.VisitAndGenerateQueryDescription(queryModel));
        }
示例#8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="QueryModelVisitor"/> class.
 /// </summary>
 /// <param name="structureBinder">The structure binder.</param>
 /// <param name="treeVisitor">The tree visitor.</param>
 /// <remarks></remarks>
 public QueryModelVisitor(AbstractQueryStructureBinder structureBinder, AbstractExpressionTreeVisitor treeVisitor)
 {
     _structureBinder = structureBinder;
     _treeVisitor     = treeVisitor;
 }
示例#9
0
        /// <summary>
        /// Rewrites the expression tree to a field predicate tree given an <see cref="AbstractQueryStructureBinder"/> implementation.
        /// </summary>
        /// <param name="expressionToVisit">The expression to visit.</param>
        /// <param name="structureBinder">The structure binder.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static Expression RewriteToFieldPredicateTree(Expression expressionToVisit, AbstractQueryStructureBinder structureBinder)
        {
            var visitor = new DefaultExpressionTreeVisitor(structureBinder);

            return(visitor.VisitExpression(expressionToVisit));
        }
示例#10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DefaultExpressionTreeVisitor"/> class.
 /// </summary>
 /// <param name="structureBinder">The structure binder.</param>
 /// <remarks></remarks>
 public DefaultExpressionTreeVisitor(AbstractQueryStructureBinder structureBinder)
 {
     StructureBinder = structureBinder;
 }