예제 #1
0
        private static void AssertTransformation(
            Expression <Func <TestClass, bool> > input,
            Expression <Func <TestClass, bool> > output)
        {
            var visitor = new BooleanOptimizingExpressionVisitor();

            var result = visitor.Visit(input.Body);

            var hasher = new HashingExpressionVisitor();

            hasher.Visit(result);

            var inputHash = hasher.HashCode;

            hasher.Reset();

            hasher.Visit(output.Body);

            var outputHash = hasher.HashCode;

            Assert.AreEqual(inputHash, outputHash, "Output expression trees do not match");
        }
예제 #2
0
        private static void AssertTransformation <TResult>(
            Expression <Func <IQueryable <MyClass1>, TResult> > input,
            Expression <Func <IQueryable <MyClass1>, TResult> > output)
        {
            var visitor = new SelectorPushdownExpressionVisitor();

            var result = visitor.Visit(input.Body);

            var hasher = new HashingExpressionVisitor();

            hasher.Visit(result);

            var inputHash = hasher.HashCode;

            hasher.Reset();

            hasher.Visit(output.Body);

            var outputHash = hasher.HashCode;

            Assert.AreEqual(inputHash, outputHash, "Output expression trees do not match");
        }
        object IQueryProvider.Execute(Expression expression)
        {
            try
            {
                var hashingVisitor = new HashingExpressionVisitor();
                expression = hashingVisitor.Visit(expression);

                var constantParameterizingVisitor = new ConstantParameterizingExpressionVisitor();
                expression = constantParameterizingVisitor.Visit(expression);

                var parameterMapping = constantParameterizingVisitor.Mapping;

                if (!QueryCache.TryGetValue(hashingVisitor.HashCode, out var compiled))
                {
                    expression = new QueryableExpandingExpressionVisitor(parameterMapping).Visit(expression);

                    expression = new PartialEvaluatingExpressionVisitor().Visit(expression);

                    var preCompositionVisitors = new[]
                    {
                        ExpressionVisitorProvider.OptimizingExpressionVisitors,
                        ExpressionVisitorProvider.MidOptimizationExpressionVisitors,
                        ExpressionVisitorProvider.OptimizingExpressionVisitors,
                    };

                    expression = preCompositionVisitors.SelectMany(vs => vs).Aggregate(expression, (e, v) => v.Visit(e));

                    expression = new QueryActivatingExpressionVisitor(this).Visit(expression);

                    expression = new QueryComposingExpressionVisitor(ExpressionVisitorProvider).Visit(expression);

                    var postCompositionVisitors = new[]
                    {
                        ExpressionVisitorProvider.OptimizingExpressionVisitors,
                    };

                    expression = postCompositionVisitors.SelectMany(vs => vs).Aggregate(expression, (e, v) => v.Visit(e));

                    var queryProviderParameter = Expression.Parameter(typeof(ImpatientQueryProvider), "queryProvider");

                    expression = new QueryCompilingExpressionVisitor(ExpressionVisitorProvider, queryProviderParameter).Visit(expression);

                    var parameters = new ParameterExpression[parameterMapping.Count + 1];

                    parameters[0] = queryProviderParameter;

                    parameterMapping.Values.CopyTo(parameters, 1);

                    compiled = Expression.Lambda(expression, parameters).Compile();

                    QueryCache.Add(hashingVisitor.HashCode, compiled);
                }

                var arguments = new object[parameterMapping.Count + 1];

                arguments[0] = this;

                parameterMapping.Keys.CopyTo(arguments, 1);

                return(compiled.DynamicInvoke(arguments));
            }
            catch (TargetInvocationException targetInvocationException)
            {
                throw targetInvocationException.InnerException;
            }
        }
예제 #4
0
        public void Hashing()
        {
            var hasher = new HashingExpressionVisitor();

            // No closure

            Expression <Func <string> > expr1 = () => "hello".ToString().Substring(0, 1);
            Expression <Func <string> > expr2 = () => "hello".ToString().Substring(0, 1);

            hasher.Visit(expr1);
            var hashCode1 = hasher.HashCode;

            hasher.Reset();

            hasher.Visit(expr2);
            var hashCode2 = hasher.HashCode;

            hasher.Reset();

            Assert.AreNotEqual(expr1, expr2);
            Assert.AreEqual(hashCode1, hashCode2);

            // Closure

            Expression <Func <string> > CreateExpressionWithClosure(int value)
            {
                Expression <Func <string> > expression = () => "hello".ToString().Substring(value, 1);

                return(expression);
            }

            var expr3 = CreateExpressionWithClosure(0);
            var expr4 = CreateExpressionWithClosure(1);

            hasher.Visit(expr3);
            var hashCode3 = hasher.HashCode;

            hasher.Reset();

            hasher.Visit(expr4);
            var hashCode4 = hasher.HashCode;

            hasher.Reset();

            Assert.AreNotEqual(expr3, expr4);
            Assert.AreEqual(hashCode3, hashCode4);

            // Partially evaluated

            var evaluator = new PartialEvaluatingExpressionVisitor();

            Expression <Func <string> > expr5 = () => "hello".ToString().Substring(0, 1);
            var expr6 = CreateExpressionWithClosure(0);

            hasher.Visit(evaluator.Visit(expr5));
            var hashCode5 = hasher.HashCode;

            hasher.Reset();

            hasher.Visit(evaluator.Visit(expr6));
            var hashCode6 = hasher.HashCode;

            hasher.Reset();

            Assert.AreNotEqual(expr5, expr6);
            Assert.AreEqual(hashCode5, hashCode6);
        }
        private static void AssertTransformation <TResult>(
            Expression <Func <IQueryable <MyClass1>, TResult> > input,
            Expression <Func <IQueryable <MyClass1>, TResult> > output)
        {
            var myClass1KeyParameter = Expression.Parameter(typeof(MyClass1), "m1");

            var myClass1KeyDescriptor
                = new PrimaryKeyDescriptor
                {
                TargetType = typeof(MyClass1),
                KeySelector
                    = Expression.Lambda(
                          Expression.MakeMemberAccess(
                              myClass1KeyParameter,
                              typeof(MyClass1).GetRuntimeProperty(nameof(MyClass1.Id))),
                          myClass1KeyParameter)
                };

            var myClass2KeyParameter = Expression.Parameter(typeof(MyClass2), "m2");

            var myClass2KeyDescriptor
                = new PrimaryKeyDescriptor
                {
                TargetType = typeof(MyClass2),
                KeySelector
                    = Expression.Lambda(
                          Expression.MakeMemberAccess(
                              myClass2KeyParameter,
                              typeof(MyClass2).GetRuntimeProperty(nameof(MyClass2.Id))),
                          myClass2KeyParameter)
                };

            var myClass1NavigationDescriptor
                = new NavigationDescriptor
                {
                Type   = typeof(MyClass1),
                Member = typeof(MyClass1).GetRuntimeProperty(nameof(MyClass1.Nav1)),
                OuterKeySelector
                    = Expression.Lambda(
                          Expression.MakeMemberAccess(
                              myClass1KeyParameter,
                              typeof(MyClass1).GetRuntimeProperty(nameof(MyClass1.Nav1Id))),
                          myClass1KeyParameter),
                InnerKeySelector = myClass2KeyDescriptor.KeySelector,
                };

            var visitor
                = new KeyEqualityRewritingExpressionVisitor(
                      primaryKeyDescriptors: new[]
            {
                myClass1KeyDescriptor,
                myClass2KeyDescriptor,
            },
                      navigationDescriptors: new[]
            {
                myClass1NavigationDescriptor,
            });

            var result = visitor.Visit(input.Body);

            var hasher = new HashingExpressionVisitor();

            hasher.Visit(result);

            var inputHash = hasher.HashCode;

            hasher.Reset();

            hasher.Visit(output.Body);

            var outputHash = hasher.HashCode;

            Assert.AreEqual(inputHash, outputHash, "Output expression trees do not match");
        }