예제 #1
0
 public override Expression LinqExpression(Dictionary<string, Expression> bindings, LinqDialect dialect)
 {
     switch (CompoundPredicateType) {
     case CompoundPredicateType.And:
       return GenerateAnd(bindings, Subpredicates, dialect);
     case CompoundPredicateType.Or:
       return GenerateOr(bindings, Subpredicates, dialect);
     case CompoundPredicateType.Not:
       return Expression.Not(Subpredicates.First().LinqExpression(bindings, dialect));
       }
       return null;
 }
예제 #2
0
        private Expression _LinqExpression(Expression left, Expression right, LinqDialect dialect)
        {
            if (0 != (Options & ComparisonPredicateOptions.CaseInsensitive) && 0 == (dialect & LinqDialect.CaseInsensitiveCollation)) {
            left = Utils.CallSafe(dialect, left, "ToLower");
            if (PredicateOperatorType != PredicateOperatorType.Matches) {
              right = Utils.CallSafe(dialect, right, "ToLower");
            }
              }

              var tuple = MakeComparable(left, right, dialect);
              left = tuple.Item1;
              right = tuple.Item2;

              switch (PredicateOperatorType) {
            case PredicateOperatorType.LessThan:
              return Expression.LessThan(left, right);
            case PredicateOperatorType.LessThanOrEqualTo:
              return Expression.LessThanOrEqual(left, right);
            case PredicateOperatorType.GreaterThan:
              return Expression.GreaterThan(left, right);
            case PredicateOperatorType.GreaterThanOrEqualTo:
              return Expression.GreaterThanOrEqual(left, right);
            case PredicateOperatorType.EqualTo:
              return Expression.Equal(left, right);
            case PredicateOperatorType.NotEqualTo:
              return Expression.NotEqual(left, right);
            case PredicateOperatorType.Matches:
              var method = typeof(Utils).GetMethod("_Predicate_MatchesRegex", BindingFlags.Public | BindingFlags.Static);
              return Expression.Call(method, left, right);
            case PredicateOperatorType.Like:
              throw new NotImplementedException();
            case PredicateOperatorType.BeginsWith:
              return Utils.CallSafe(dialect, left, "StartsWith", right);
            case PredicateOperatorType.EndsWith:
              return Utils.CallSafe(dialect, left, "EndsWith", right);
            case PredicateOperatorType.In:
              return Utils.CallSafe(dialect, right, "Contains", left);
            case PredicateOperatorType.Contains:
              return Utils.CallSafe(dialect, left, "Contains", right);
            case PredicateOperatorType.Between:
              Expression lower, upper;
              if (right.Type.IsSubclassOf(typeof(Array))) {
            lower = Expression.ArrayIndex(right, Expression.Constant(0));
            upper = Expression.ArrayIndex(right, Expression.Constant(1));
              } else {
            lower = Expression.Property(right, "Item", Expression.Constant(0));
            upper = Expression.Property(right, "Item", Expression.Constant(1));
              }
              return Expression.AndAlso(Expression.GreaterThanOrEqual(left, lower), Expression.LessThanOrEqual(left, upper));
              }
              return null;
        }
예제 #3
0
 private Expression MakeComparableVector(Expression needle, Expression haystack, LinqDialect dialect)
 {
     var haystackElementType = Utils.ElementType(haystack.Type);
       int order = CompareTypePrecision(haystackElementType, needle.Type);
       if (order != 0) {
     return Cast(needle, haystackElementType);
       } else {
     return needle;
       }
 }
예제 #4
0
        private Tuple<Expression, Expression> MakeComparableScalar(Expression left, Expression right, LinqDialect dialect)
        {
            var lr = PromoteNullableValueTypes(left, right);

              var exprs = new Expression[] { lr.Item1, lr.Item2 };
              Array.Sort(exprs, CompareExpressionTypePrecision);
              bool needsFlip = exprs[0] == right;

              if (exprs[0].Type != exprs[1].Type) {
            exprs[0] = Cast(exprs[0], exprs[1].Type);
              }

              if (needsFlip) {
            Array.Reverse(exprs);
              }
              return new Tuple<Expression, Expression>(exprs[0], exprs[1]);
        }
예제 #5
0
 private Tuple<Expression, Expression> MakeComparable(Expression left, Expression right, LinqDialect dialect)
 {
     if (left.Type == right.Type) {
     return new Tuple<Expression, Expression>(left, right);
       } else if (Utils.TypeIsEnumerable(left.Type) && !Utils.TypeIsEnumerable(right.Type)) {
     return new Tuple<Expression, Expression>(left, MakeComparableVector(right, left, dialect));
       } else if (Utils.TypeIsEnumerable(right.Type) && !Utils.TypeIsEnumerable(left.Type)) {
     return new Tuple<Expression, Expression>(MakeComparableVector(left, right, dialect), right);
       } else if (IsCastableType(left.Type) && IsCastableType(right.Type)) {
     return MakeComparableScalar(left, right, dialect);
       } else {
     // Hope there is some comparison overload already defined for us
     return new Tuple<Expression, Expression>(left, right);
       }
 }
예제 #6
0
        public override Expression LinqExpression(Dictionary<string, Expression> bindings, LinqDialect dialect)
        {
            Expression left = LeftExpression.LinqExpression(bindings, dialect);
              Expression right = RightExpression.LinqExpression(bindings, dialect);

              if (ComparisonPredicateModifier != ComparisonPredicateModifier.Direct) {
            ParameterExpression t = Expression.Parameter(Utils.ElementType(left.Type));
            Expression filter = Expression.Lambda(_LinqExpression(t, right, dialect), new ParameterExpression[] { t });
            if (ComparisonPredicateModifier == ComparisonPredicateModifier.All) {
              Expression all = Utils.CallAggregate("All", left, filter);
              return all;
            } else if (ComparisonPredicateModifier == ComparisonPredicateModifier.Any) {
              Expression any = Utils.CallAggregate("Any", left, filter);
              return any;
            } else {
              throw new NotImplementedException($"Unhandled ComparisonPredicateModifier {ComparisonPredicateModifier}");
            }
              } else {
            return _LinqExpression(left, right, dialect);
              }
        }
예제 #7
0
 private Expression GenerateOr(Dictionary<string, Expression> bindings, IEnumerable<Predicate> predicates, LinqDialect dialect)
 {
     if (predicates.Count() > 2) {
     Expression a = predicates.First().LinqExpression(bindings, dialect);
     Expression b = GenerateOr(bindings, predicates.Skip(1), dialect);
     return Expression.OrElse(a, b);
       } else if (predicates.Count() == 2) {
     Expression a = predicates.First().LinqExpression(bindings, dialect);
     Expression b = predicates.Last().LinqExpression(bindings, dialect);
     return Expression.OrElse(a, b);
       } else if (predicates.Count() == 1) {
     return predicates.First().LinqExpression(bindings, dialect);
       } else {
     return new ConstantPredicate(false).LinqExpression(bindings, dialect);
       }
 }
예제 #8
0
 public override Expression LinqExpression(Dictionary<string, Expression> bindings, LinqDialect dialect)
 {
     return Expression.Constant(Value);
 }
예제 #9
0
 public static Expression CallSafe(LinqDialect dialect, Expression target, string methodName, params Expression[] arguments)
 {
     if ((dialect & LinqDialect.EntityFramework) == 0) {
     var defaultTarget = Expression.Default(target.Type);
     var isNull = Expression.ReferenceEqual(target, defaultTarget);
     var argTypes = arguments.Select(a => a.Type).ToArray();
     var called = Expression.Call(target, target.Type.GetMethod(methodName, argTypes), arguments);
     var defaultCalled = Expression.Default(called.Type);
     return Expression.Condition(isNull, defaultCalled, called);
       } else {
     var argTypes = arguments.Select(a => a.Type).ToArray();
     return Expression.Call(target, target.Type.GetMethod(methodName, argTypes), arguments);
       }
 }