public static Expression CreateFilterExpression(Type type, InvocationQuerySyntaxNode node) { var visitor = new ExpressionFilterQuerySyntaxVisitor(type); var filterBody = visitor.Visit(node); return(Expression.Lambda(filterBody, visitor.Parameter)); }
public static Expression CreateSelectExpression(Type type, InvocationQuerySyntaxNode node) { var visitor = new ExpressionSelectQuerySyntaxVisitor(type); var selectBody = visitor.Visit(node); return(Expression.Lambda(selectBody, visitor.Parameter)); }
/// <summary> /// Возвращает набор функций сортировки документов. /// </summary> protected IEnumerable <InvocationQuerySyntaxNode> ParseOrder(IHttpRequest request) { var parameter = GetQueryParameter(request, QuerySyntaxHelper.OrderParameterName); if (parameter != null) { var syntaxNodes = _syntaxTreeParser.Parse(parameter); if (syntaxNodes != null && syntaxNodes.Count > 0) { foreach (var node in syntaxNodes) { var invocationNode = node as InvocationQuerySyntaxNode; if (invocationNode != null) { yield return(invocationNode); } else { // По умолчанию перечисление полей объединяется методом asc() var asc = new InvocationQuerySyntaxNode(QuerySyntaxHelper.AscMethodName); asc.Arguments.Add(node); yield return(asc); } } } } }
public static Action <IDocumentProjectionBuilder> CreateSelectExpression(InvocationQuerySyntaxNode node) { var visitor = new FuncSelectQuerySyntaxVisitor(); var selectBody = visitor.Visit(node); return(selectBody); }
public static Func <IDocumentFilterBuilder, object> CreateFilterExpression(InvocationQuerySyntaxNode node) { var visitor = new FuncFilterQuerySyntaxVisitor(); var filterBody = visitor.Visit(node); return(filterBody); }
// Overrides public override Expression VisitInvocationExpression(InvocationQuerySyntaxNode node) { if (!string.Equals(node.Name, QuerySyntaxHelper.IncludeMethodName, StringComparison.OrdinalIgnoreCase)) { return(base.VisitInvocationExpression(node)); } return(QuerySyntaxHelper.Projection(node.Arguments.Select(Visit))); }
// Overrides public override Expression VisitInvocationExpression(InvocationQuerySyntaxNode node) { Func <ExpressionFilterQuerySyntaxVisitor, InvocationQuerySyntaxNode, Expression> factory; if (!KnownFunctions.TryGetValue(node.Name, out factory)) { return(base.VisitInvocationExpression(node)); } return(factory(this, node)); }
/// <summary> /// Возвращает функцию фильтрации документов. /// </summary> protected InvocationQuerySyntaxNode ParseFilter(IHttpRequest request, string documentIdKey) { InvocationQuerySyntaxNode filter = null; // Если определен фильтр по идентификатору документа var documentId = GetRequestParameter(request, documentIdKey); if (!string.IsNullOrEmpty(documentId)) { filter = new InvocationQuerySyntaxNode(QuerySyntaxHelper.EqMethodName); filter.Arguments.Add(new IdentifierNameQuerySyntaxNode("_id")); filter.Arguments.Add(new LiteralQuerySyntaxNode(documentId)); } // Если определено условие фильтрации else { var documentQuery = GetQueryParameter(request, QuerySyntaxHelper.FilterParameterName); if (documentQuery != null) { var syntaxNodes = _syntaxTreeParser.Parse(documentQuery); if (syntaxNodes != null && syntaxNodes.Count > 0) { if (syntaxNodes.Count == 1) { return(syntaxNodes[0] as InvocationQuerySyntaxNode); } // По умолчанию все условия объединяются методом and() var and = new InvocationQuerySyntaxNode(QuerySyntaxHelper.AndMethodName); and.Arguments.AddRange(syntaxNodes); return(and); } } } return(filter); }
// Overrides public override Expression VisitInvocationExpression(InvocationQuerySyntaxNode node) { if (string.Equals(node.Name, QuerySyntaxHelper.AscMethodName, StringComparison.OrdinalIgnoreCase)) { var ascProperties = node.Arguments.Select(Visit) .OfType <MemberExpression>() .Select(i => new KeyValuePair <Expression, DocumentSortOrder>(Expression.Lambda(QuerySyntaxHelper.Convert(i, typeof(object)), Parameter), DocumentSortOrder.Asc)) .ToArray(); return(Expression.Constant(ascProperties)); } if (string.Equals(node.Name, QuerySyntaxHelper.DescMethodName, StringComparison.OrdinalIgnoreCase)) { var descProperties = node.Arguments.Select(Visit) .OfType <MemberExpression>() .Select(i => new KeyValuePair <Expression, DocumentSortOrder>(Expression.Lambda(QuerySyntaxHelper.Convert(i, typeof(object)), Parameter), DocumentSortOrder.Desc)) .ToArray(); return(Expression.Constant(descProperties)); } return(base.VisitInvocationExpression(node)); }
private static Expression CreateSizeFilterForArrayProperty(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node, Func <Expression, Expression, Expression> filter) { // filter(arrayProperty, value) --> filter(Enumerable.Count(i.arrayProperty), value) var arrayProperty = visitor.Visit(node.Arguments[0]); var value = visitor.Visit(node.Arguments[1]); var itemType = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type); return(QuerySyntaxHelper.Compare(QuerySyntaxHelper.InvokeCount(itemType, arrayProperty), value, filter)); }
private static Expression NotInInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // notIn(property, value1, value2, value3, ...) --> !Enumerable.Contains(new[] { value1, value2, value3, ... }, i.property) return(Expression.Not(InInvocation(visitor, node))); }
// Helpers private static Expression CreateFilterForArrayProperty(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node, Func <Type, Expression, Expression, Expression> filter) { // filter(arrayProperty, item1, item2, item3, ...) --> filter(new[] { item1, item2, item3, ... }, ii => Enumerable.Contains(i.arrayProperty, ii)) var arrayProperty = visitor.Visit(node.Arguments[0]); var itemType = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type); var items = QuerySyntaxHelper.NewArray(itemType, node.Arguments.Skip(1).Select(visitor.Visit)); var itemParameter = Expression.Parameter(itemType); var itemFilter = QuerySyntaxHelper.InvokeContains(itemType, arrayProperty, itemParameter); return(filter(itemType, items, Expression.Lambda(itemFilter, itemParameter))); }
private static Expression CreateAnyFilterForArrayProperty(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node, Func <Expression, Expression, Expression> filter) { // filter(arrayProperty, item) --> Enumerable.Any(i.arrayProperty, ii => filter(ii, item)) var arrayProperty = visitor.Visit(node.Arguments[0]); var item = visitor.Visit(node.Arguments[1]); var itemType = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type); var itemParameter = Expression.Parameter(itemType); return(QuerySyntaxHelper.InvokeAny(itemType, arrayProperty, Expression.Lambda(QuerySyntaxHelper.Compare(itemParameter, item, filter), itemParameter))); }
public static IEnumerable <KeyValuePair <Expression, DocumentSortOrder> > CreateOrderExpression(Type type, InvocationQuerySyntaxNode node) { var visitor = new ExpressionOrderQuerySyntaxVisitor(type); var orderProperties = (ConstantExpression)visitor.Visit(node); return((IEnumerable <KeyValuePair <Expression, DocumentSortOrder> >)orderProperties.Value); }
private static Expression RegexInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // regex(property, pattern, 'option1', 'option2', 'option3', ...) --> Regex.IsMatch(i.property, pattern, option1 | option2 | option3 | ...) var property = visitor.Visit(node.Arguments[0]); var pattern = visitor.Visit(node.Arguments[1]); var options = Expression.Constant(node.Arguments.Skip(2).Aggregate(RegexOptions.None, (r, n) => r | n.AsEnumIdentifier <RegexOptions>())); return(QuerySyntaxHelper.InvokeRegex(property, pattern, options)); }
private static Expression AnyLteInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // anyLte(arrayProperty, item) --> Enumerable.Any(i.arrayProperty, ii => ii <= item) return(CreateAnyFilterForArrayProperty(visitor, node, Expression.LessThanOrEqual)); }
private static Expression OrInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // or(condition1, condition2, condition3, ...) --> (((condition1 || condition2) || condition3) || ...) Expression result = null; var conditions = node.Arguments.Select(visitor.Visit); foreach (var condition in conditions) { result = (result != null) ? Expression.OrElse(result, condition) : condition; } return(result); }
private static Expression AnyNotEqInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // anyNotEq(arrayProperty, item) --> !Enumerable.Any(i.arrayProperty, ii => ii == item) return(Expression.Not(AnyEqInvocation(visitor, node))); }
private static Expression GtInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // gt(property, value) --> i.property > value var property = visitor.Visit(node.Arguments[0]); var value = visitor.Visit(node.Arguments[1]); return(QuerySyntaxHelper.Compare(property, value, Expression.GreaterThan)); }
private static Expression AnyNotInInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // anyNotIn(arrayProperty, item1, item2, item3, ...) --> !Enumerable.Any(new[] { item1, item2, item3, ... }, ii => Enumerable.Contains(i.arrayProperty, ii)) return(Expression.Not(AnyInInvocation(visitor, node))); }
private static Expression AnyInInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // anyIn(arrayProperty, item1, item2, item3, ...) --> Enumerable.Any(new[] { item1, item2, item3, ... }, ii => Enumerable.Contains(i.arrayProperty, ii)) return(CreateFilterForArrayProperty(visitor, node, QuerySyntaxHelper.InvokeAny)); }
private static Expression MatchInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // match(arrayProperty, filter) --> Enumerable.Any(i.arrayProperty, ii => filter(ii)) var arrayProperty = visitor.Visit(node.Arguments[0]); var itemType = QuerySyntaxHelper.GetCollectionItemType(arrayProperty.Type); var itemFilter = CreateFilterExpression(itemType, (InvocationQuerySyntaxNode)node.Arguments[1]); return(QuerySyntaxHelper.InvokeAny(itemType, arrayProperty, itemFilter)); }
private static Expression InInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // in(property, value1, value2, value3, ...) --> Enumerable.Contains(new[] { value1, value2, value3, ... }, i.property) var property = visitor.Visit(node.Arguments[0]); var values = QuerySyntaxHelper.NewArray(property.Type, node.Arguments.Skip(1).Select(visitor.Visit)); return(QuerySyntaxHelper.InvokeContains(property.Type, values, property)); }
private static Expression SizeGtInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // sizeGt(arrayProperty, value) --> Enumerable.Count(i.arrayProperty) > value return(CreateSizeFilterForArrayProperty(visitor, node, Expression.GreaterThan)); }
// KnownFunctions private static Expression NotInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // not(condition) --> !condition var condition = visitor.Visit(node.Arguments[0]); return(Expression.Not(condition)); }
private static Expression SizeLteInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // sizeLte(arrayProperty, value) --> Enumerable.Count(i.arrayProperty) <= value return(CreateSizeFilterForArrayProperty(visitor, node, Expression.LessThanOrEqual)); }
/// <summary> /// Обрабатывает вызов метода. /// </summary> public virtual TResult VisitInvocationExpression(InvocationQuerySyntaxNode node) { return(DefaultVisit(node)); }
private static Expression DateInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // date('value') --> DateTime.Parse('value') var dateTimeString = node.Arguments[0].AsStringLiteral(); var dateTime = DateTime.Parse(dateTimeString); return(Expression.Constant(dateTime)); }
private static Expression AnyGtInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // anyGt(arrayProperty, item) --> Enumerable.Any(i.arrayProperty, ii => ii > item) return(CreateAnyFilterForArrayProperty(visitor, node, Expression.GreaterThan)); }
private static Expression LteInvocation(ExpressionFilterQuerySyntaxVisitor visitor, InvocationQuerySyntaxNode node) { // lte(property, value) --> i.property <= value var property = visitor.Visit(node.Arguments[0]); var value = visitor.Visit(node.Arguments[1]); return(QuerySyntaxHelper.Compare(property, value, Expression.LessThanOrEqual)); }