public static OpenTypeMethodsImplementation GetImplementation(OpenTypeMethodsImplementations type, bool lazyEvaluation) { OpenTypeMethodsImplementation impl = null; switch (type) { case OpenTypeMethodsImplementations.Default: impl = new DefaultOpenTypeMethodsImplementation(); break; case OpenTypeMethodsImplementations.Realistic: impl = new RealisticOpenTypeMethodsImplementation(); break; case OpenTypeMethodsImplementations.Tolerant: impl = new TolerantOpenTypeMethodsImplementation(); break; default: return(null); } impl.UseLazyBooleanEvaluation = lazyEvaluation; return(impl); }
/// <summary> /// Visits a method call expression /// </summary> /// <param name="m">The method call expression</param> /// <returns>A new expression after the parameter is visited</returns> internal override Expression VisitMethodCall(MethodCallExpression m) { MethodInfo method = m.Method; if (method.ReflectedType == typeof(DataServiceProviderMethods)) { if (DSPMethodsImplementation.ShouldReplaceMethod(method)) { return(DSPMethodsImplementation.ConvertMethodCall(method, this.VisitExpressionList(m.Arguments))); } else { return(base.VisitMethodCall(m)); } } else if (method.ReflectedType == typeof(OpenTypeMethods)) { if (OpenTypeMethodsImplementation.UseLazyBooleanEvaluation) { Expression left = this.Visit(m.Arguments[0]); Expression right = this.Visit(m.Arguments[1]); ParameterExpression param = Expression.Parameter(typeof(object), "leftSideLazyEvaluator"); if (method.Name.StartsWith("And") || method.Name.StartsWith("Or")) { bool lazyValue = method.Name.StartsWith("And"); // if the left-hand side evaluates to a boolean constant that allows lazy evaluation, // then do not evaluate the right hand side right = Expression.Condition( Expression.And( Expression.TypeIs(param, typeof(bool)), Expression.Equal(Expression.Convert(param, typeof(bool)), Expression.Constant(!lazyValue))), Expression.Constant(false, typeof(object)), right); } Expression call = OpenTypeMethodsImplementation.ConvertMethodCall(method, param, right); return(Expression.Invoke(Expression.Lambda(call, param), left)); } else { return(OpenTypeMethodsImplementation.ConvertMethodCall(method, this.VisitExpressionList(m.Arguments))); } } else if (method.ReflectedType == typeof(Queryable)) { if (method.Name.StartsWith("OrderBy") || method.Name.StartsWith("ThenBy")) { // untyped orderby, must be late bound, use our comparison instead of the default if (method.GetGenericArguments()[1] == typeof(object)) { return(Expression.Call(typeof(Queryable), method.Name, method.GetGenericArguments(), this.Visit(m.Arguments[0]), this.Visit(m.Arguments[1]), Expression.Constant(this.OpenTypeMethodsImplementation))); } } } return(base.VisitMethodCall(m)); }
/// <summary> /// BinaryExpression visit method /// </summary> /// <param name="b">The BinaryExpression expression to visit</param> /// <returns>The visited BinaryExpression expression </returns> internal override Expression VisitBinary(BinaryExpression b) { MethodInfo method = b.Method; if (method != null && method.ReflectedType == typeof(OpenTypeMethods)) { return(OpenTypeMethodsImplementation.ConvertMethodCall(method, this.Visit(b.Left), this.Visit(b.Right))); } return(base.VisitBinary(b)); }
/// <summary> /// BinaryExpression visit method /// </summary> /// <param name="b">The BinaryExpression expression to visit</param> /// <returns>The visited BinaryExpression expression </returns> internal override Expression VisitUnary(UnaryExpression u) { MethodInfo method = u.Method; if (method != null && method.ReflectedType == typeof(OpenTypeMethods)) { return(OpenTypeMethodsImplementation.ConvertMethodCall(method, this.Visit(u.Operand))); } return(base.VisitUnary(u)); }
/// <summary> /// Creates a new instance of LateBoundExpressionVisitor /// </summary> /// <param name="evaluator">An evaluator class in which expressions will be bound to.</param> /// <param name="provider">The provider</param> internal LateBoundExpressionVisitor(OpenTypeMethodsImplementation openTypeImplementation, DSPMethodsImplementation dspImplementation) { this.OpenTypeMethodsImplementation = openTypeImplementation; this.DSPMethodsImplementation = dspImplementation; }