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"); }
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; } }
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"); }