/// <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)); }
private static void UpdateValuePredicateType(BindingSignatureSupport signatureSupport, BinaryExpression binaryExpression) { // Only modify the ValuePredicateType if it already is "Equals" or "Empty". This is pending a refactor // of BindingSignatureSupport to include a negation property and the removal of NotEquals if (signatureSupport.NodeType != ValuePredicateType.Equal && signatureSupport.NodeType != ValuePredicateType.Empty) { return; } // First check the NodeType. Binaries joined with "!= true" will have a NodeType of NotEqual switch (binaryExpression.NodeType) { case ExpressionType.Equal: signatureSupport.NodeType = ValuePredicateType.Equal; break; case ExpressionType.NotEqual: signatureSupport.NodeType = ValuePredicateType.NotEqual; break; case ExpressionType.GreaterThan: signatureSupport.NodeType = ValuePredicateType.GreaterThan; break; case ExpressionType.GreaterThanOrEqual: signatureSupport.NodeType = ValuePredicateType.GreaterThanOrEqual; break; case ExpressionType.LessThan: signatureSupport.NodeType = ValuePredicateType.LessThan; break; case ExpressionType.LessThanOrEqual: signatureSupport.NodeType = ValuePredicateType.LessThanOrEqual; break; } // Then check the Method, which might be an operator if (binaryExpression.Method != null) { switch (binaryExpression.Method.Name) { case "op_Inequality": signatureSupport.NodeType = ValuePredicateType.NotEqual; break; } } }
public override FieldSelectorExpression CreateFieldSelector(MemberExpression expression, BindingSignatureSupport reportedSignatureSupport) { var attrib = GetAutoAttribute(expression); return(attrib == null?base.CreateFieldSelector(expression, reportedSignatureSupport) : new FieldSelectorExpression(attrib.Alias)); }
/// <summary> /// Creates a <see cref="FieldSelectorExpression"/> from a <see cref="MethodCallExpression"/>. /// </summary> /// <param name="expression">The expression.</param> /// <param name="reportedSignatureSupport">A component outlining the supported expression structure of this provider.</param> /// <returns></returns> /// <remarks></remarks> public override FieldSelectorExpression CreateFieldSelector(MethodCallExpression expression, BindingSignatureSupport reportedSignatureSupport) { switch (expression.Method.Name) { case "Field": // This is an extension method for the RenderViewModel so the first argument is the extended object return(new FieldSelectorExpression(((ConstantExpression)expression.Arguments[1]).Value.ToString())); case "StringField": // This is an extension method for the RenderViewModel so the first argument is the extended object return(new FieldSelectorExpression(((ConstantExpression)expression.Arguments[1]).Value.ToString())); case "NumberField": // This is an extension method for the RenderViewModel so the first argument is the extended object return(new FieldSelectorExpression(((ConstantExpression)expression.Arguments[1]).Value.ToString())); case "BooleanField": // This is an extension method for the RenderViewModel so the first argument is the extended object return(new FieldSelectorExpression(((ConstantExpression)expression.Arguments[1]).Value.ToString())); case "get_Item": // This is the default accessor of a Dictionary, so check if the parent object is supported too if (ExpressionHelper.IsMember(expression.Object) && IsSupportedMember(expression.Object as MemberExpression).SignatureSupportType != SignatureSupportType.NotSupported) { return(new FieldSelectorExpression(((ConstantExpression)expression.Arguments[0]).Value.ToString())); } break; } return(base.CreateFieldSelector(expression, reportedSignatureSupport)); }
/// <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); }
/// <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); }
/// <summary> /// Creates a <see cref="FieldSelectorExpression"/> from a <see cref="MethodCallExpression"/>. /// </summary> /// <param name="expression">The expression.</param> /// <param name="reportedSignatureSupport">A component outlining the supported expression structure of this provider.</param> /// <returns></returns> /// <remarks></remarks> public override FieldSelectorExpression CreateFieldSelector(MethodCallExpression expression, BindingSignatureSupport reportedSignatureSupport) { switch (expression.Method.Name) { case "Attribute": // This is an extension method for the Persistence model so the first argument is the extended object if (expression.Arguments.Count == 3) { //if there are 3 arguments, then we are selecting a field by name with a value key return(new FieldSelectorExpression( ((ConstantExpression)expression.Arguments[1]).Value.ToString(), ((ConstantExpression)expression.Arguments[2]).Value.ToString())); } if (expression.Arguments.Count == 2) { //if there are 2 arguments, then we are selecting a field only by name regardless of the value key return(new FieldSelectorExpression(((ConstantExpression)expression.Arguments[1]).Value.ToString())); } break; case "get_Item": // This is the default accessor of a Dictionary, so check if the parent object is supported too if (ExpressionHelper.IsMember(expression.Object) && IsSupportedMember(expression.Object as MemberExpression).SignatureSupportType != SignatureSupportType.NotSupported) { return(new FieldSelectorExpression(((ConstantExpression)expression.Arguments[0]).Value.ToString())); } // There are two dictionaries on this model, the TypedAttributeCollection and its child TypedAttributeValueCollection. // Make sure we're getting the field name from the TypedAttributeCollection indexer. To do this, access the MemberExpression // "one up the chain" and recurse back into this method. if (ExpressionHelper.IsMember(expression.Object) && ExpressionHelper.IsMethod(((MemberExpression)expression.Object).Expression)) { return(CreateFieldSelector(((MemberExpression)expression.Object).Expression as MethodCallExpression, reportedSignatureSupport)); } break; } return(base.CreateFieldSelector(expression, reportedSignatureSupport)); }
/// <summary> /// Creates a field selector. /// </summary> /// <param name="fieldName">Name of the field.</param> /// <param name="innerFieldName">Name of the inner field.</param> /// <param name="reportedSignatureSupport">The reported signature support.</param> /// <returns></returns> public override FieldSelectorExpression CreateFieldSelector(string fieldName, string innerFieldName, BindingSignatureSupport reportedSignatureSupport) { switch (fieldName) { case "Name": return(new FieldSelectorExpression("system-internal-node-name", fieldName)); case "UrlName": return(new FieldSelectorExpression("system-internal-node-name", fieldName)); case "Template": case "TemplateId": case "CurrentTemplate": return(new FieldSelectorExpression("system-internal-selected-template", "TemplateId")); default: return(base.CreateFieldSelector(fieldName, innerFieldName, reportedSignatureSupport)); } }