public void EnsureComparable(Type type, RsqlParser.ComparisonContext context) { type = type ?? throw new ArgumentNullException(nameof(type)); context = context ?? throw new ArgumentNullException(nameof(context)); var effectiveType = type.FindNullableValueType() ?? type; if (!this.IsComparableType(effectiveType)) { throw new InvalidComparatorException(context); } }
public virtual Expression <Func <T, bool> > BuildComparison <T>( string comparator, ParameterExpression parameter, RsqlParser.ComparisonContext context) { comparator = comparator ?? throw new ArgumentNullException(nameof(comparator)); parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); context = context ?? throw new ArgumentNullException(nameof(context)); switch (comparator) { case "==": case "=eq=": return(this.EqualComparator <T>(parameter, context)); case "!=": case "=neq=": return(this.NotEqualComparator <T>(parameter, context)); case "<": case "=lt=": return(this.LessThanComparator <T>(parameter, context)); case "<=": case "=le=": return(this.LessOrEqualComparator <T>(parameter, context)); case ">": case "=gt=": return(this.GreaterThanComparator <T>(parameter, context)); case ">=": case "=ge=": return(this.GreaterOrEqualComparator <T>(parameter, context)); case "=is-null=": case "=nil=": return(this.IsNullComparator <T>(parameter, context)); case "=in=": return(this.InComparator <T>(parameter, context)); case "=out=": case "=nin=": return(this.NotInComparator <T>(parameter, context)); default: throw new UnknownComparatorException(context); } }
private static object GetSingleValue(Type type, RsqlParser.ComparisonContext context) { type = type ?? throw new ArgumentNullException(nameof(type)); context = context ?? throw new ArgumentNullException(nameof(context)); var value = context.arguments().value(); if (value.Length > 1) { throw new TooManyArgumentsException(context); } return(ValueParser.GetValue(type, value.First())); }
public InvalidComparatorException(RsqlParser.ComparisonContext context, Exception?innerException = null) : base(context, $"Invalid comparator: {context.selector().GetText()}", innerException) { }
public override Expression <Func <T, bool> > VisitComparison(RsqlParser.ComparisonContext context) { var comparator = context.comparator().GetText().ToLowerInvariant(); return(this._expressionHelper.BuildComparison <T>(comparator, this._parameter, context)); }
/// <summary> /// Visit a parse tree produced by <see cref="RsqlParser.comparison"/>. /// <para> /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/> /// on <paramref name="context"/>. /// </para> /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public virtual Result VisitComparison([NotNull] RsqlParser.ComparisonContext context) { return(VisitChildren(context)); }
public UnknownComparatorException(RsqlParser.ComparisonContext context, Exception?innerException = null) : base(context, $"Unknown comparator: {context.comparator().GetText()}", innerException) { }
public TooManyArgumentsException(RsqlParser.ComparisonContext context, Exception?innerException = null) : base(context, $"Too many arguments: {context.selector().GetText()}", innerException) { }
public Expression <Func <T, bool> > NotInComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context) { parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); context = context ?? throw new ArgumentNullException(nameof(context)); var expression = this.InComparator <T>(parameter, context); var body = Expression.Not(expression.Body); return(Expression.Lambda <Func <T, bool> >(body, parameter)); }
public Expression <Func <T, bool> > InComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context) { parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); context = context ?? throw new ArgumentNullException(nameof(context)); var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText()); this.EnsureEquatable(expressionPath.Type, context); var values = ValueParser.GetValues(expressionPath.Type, context.arguments()); var methodContainsInfo = ContainsHelper.GetOrRegistryContainsMethodInfo(expressionPath.Type); return(Expression.Lambda <Func <T, bool> >( ComparisonBuilder.PathNotNull( expressionPath, Expression.Call( Expression.Constant(methodContainsInfo.Convert(values)), methodContainsInfo.ContainsMethod, expressionPath.Expression)), parameter)); }
public Expression <Func <T, bool> > LikeComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context) { parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); context = context ?? throw new ArgumentNullException(nameof(context)); var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText()); if (expressionPath.Type != typeof(string)) { throw new InvalidComparatorException(context); } var like = (string)ComparisonBuilder.GetSingleValue(expressionPath.Type, context); like = like.Replace(@"\*", ComparisonBuilder.EscapedLikePlaceholder); MethodInfo method; var startsWild = like.StartsWith("*"); var endsWild = like.EndsWith("*"); if (!startsWild && endsWild) { method = ContainsHelper.StringStartsWithMethod; } else if (startsWild && !endsWild) { method = ContainsHelper.StringEndsWithMethod; } else { method = ContainsHelper.StringContainsMethod; } like = like.Replace("*", string.Empty).Replace(ComparisonBuilder.EscapedLikePlaceholder, "*"); return(Expression.Lambda <Func <T, bool> >( ComparisonBuilder.FullPathNotNull( expressionPath, Expression.Call( expressionPath.Expression, method, Expression.Constant(like, expressionPath.Type))), parameter)); }
public Expression <Func <T, bool> > GreaterOrEqualComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context) { parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); context = context ?? throw new ArgumentNullException(nameof(context)); var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText()); this.EnsureComparable(expressionPath.Type, context); var value = ComparisonBuilder.GetSingleValue(expressionPath.Type, context); return(Expression.Lambda <Func <T, bool> >( ComparisonBuilder.PathNotNull( expressionPath, Expression.GreaterThanOrEqual( expressionPath.Expression, Expression.Constant(value, expressionPath.Type))), parameter)); }
public Expression <Func <T, bool> > IsNullComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context) { parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); context = context ?? throw new ArgumentNullException(nameof(context)); var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText()); var value = (bool)ComparisonBuilder.GetSingleValue(typeof(bool), context); var lastNullableExpression = expressionPath.ExpressionSteps.LastOrDefault(e => ComparisonBuilder.CanBeNull(e.Type)); if (lastNullableExpression == null) { // Can never be null return(Expression.Lambda <Func <T, bool> >(Expression.Constant(!value), parameter)); } var result = Expression.Lambda <Func <T, bool> >( ComparisonBuilder.PathCanBeNull( expressionPath, Expression.Equal( lastNullableExpression, Expression.Constant(null, typeof(object)))), parameter); if (value) { return(result); } var body = Expression.Not(result.Body); result = Expression.Lambda <Func <T, bool> >(body, parameter); return(result); }
public Expression <Func <T, bool> > EqualComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context) { parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); context = context ?? throw new ArgumentNullException(nameof(context)); var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText()); this.EnsureEquatable(expressionPath.Type, context); var value = ComparisonBuilder.GetSingleValue(expressionPath.Type, context); if (expressionPath.Type != typeof(string)) { return(Expression.Lambda <Func <T, bool> >( ComparisonBuilder.PathNotNull( expressionPath, Expression.Equal( expressionPath.Expression, Expression.Constant(value, expressionPath.Type) )), parameter)); } var escapedLike = ((string)value).Replace(@"\*", ComparisonBuilder.EscapedLikePlaceholder); if (escapedLike.Contains('*')) { return(this.LikeComparator <T>(parameter, context)); } escapedLike = escapedLike.Replace(ComparisonBuilder.EscapedLikePlaceholder, "*"); return(Expression.Lambda <Func <T, bool> >( ComparisonBuilder.PathNotNull( expressionPath, Expression.Equal( expressionPath.Expression, Expression.Constant(escapedLike, expressionPath.Type))), parameter)); }