When implemented in a derived class, provides a mechanism to assess certain types of expression and determine whether they are supported by the provider. For example, implementors of this class may advertise that the expression for the System.String.EndsWith(string) is supported.
コード例 #1
0
        /// <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);
        }
コード例 #2
0
        /// <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;
        }
コード例 #3
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);
 }
コード例 #4
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;
 }
コード例 #5
0
 /// <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;
 }
コード例 #6
0
 public static FieldSelectorExpression GetFieldSelector(Expression left, AbstractQueryStructureBinder structureBinder)
 {
     var signatureSupport = GetBindingSupport(left, structureBinder);
     return GetFieldSelector(left, structureBinder, signatureSupport);
 }
コード例 #7
0
 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;
 }
コード例 #8
0
        /// <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;
        }