1- using System . Collections . Generic ;
1+ using System . Collections . Generic ;
22using System . Linq ;
33using System . Linq . Expressions ;
44using System . Reflection ;
@@ -12,6 +12,50 @@ public static Expression Decompile(Expression expression)
1212 return new DecompileExpressionVisitor ( ) . Visit ( expression ) ;
1313 }
1414
15+ private static readonly object NULL = new object ( ) ; // for use as a dictionary key
16+ private readonly Dictionary < object , Expression > visitedConstants ;
17+
18+ private bool hasAnyChanges = false ;
19+ public override Expression Visit ( Expression node )
20+ {
21+ var result = base . Visit ( node ) ;
22+ if ( result != node )
23+ hasAnyChanges = true ;
24+ return result ;
25+ }
26+
27+ private DecompileExpressionVisitor ( Dictionary < object , Expression > sharedVisitedConstants = null )
28+ {
29+ this . visitedConstants = sharedVisitedConstants ?? new Dictionary < object , Expression > ( ) ;
30+ }
31+
32+ protected override Expression VisitConstant ( ConstantExpression node )
33+ {
34+ Expression result ;
35+ if ( visitedConstants . TryGetValue ( node . Value ?? NULL , out result ) )
36+ {
37+ return result ; // avoid infinite recursion
38+ }
39+
40+ if ( typeof ( IQueryable ) . IsAssignableFrom ( node . Type ) )
41+ {
42+ visitedConstants . Add ( node . Value ?? NULL , node ) ;
43+
44+ var value = ( IQueryable ) node . Value ;
45+ var childVisitor = new DecompileExpressionVisitor ( visitedConstants ) ;
46+ result = childVisitor . Visit ( value . Expression ) ;
47+
48+ if ( childVisitor . hasAnyChanges )
49+ {
50+ result = Expression . Constant ( value . Provider . CreateQuery ( result ) , node . Type ) ;
51+ visitedConstants [ node . Value ?? NULL ] = result ;
52+ return result ;
53+ }
54+ }
55+
56+ return node ;
57+ }
58+
1559 protected override Expression VisitMember ( MemberExpression node )
1660 {
1761 if ( ShouldDecompile ( node . Member ) && node . Member is PropertyInfo property )
0 commit comments