Skip to content

Commit 33a0003

Browse files
committed
Merge branch 'develop' of https://github.com/txavier/DelegateDecompiler into txavier-develop
2 parents a712784 + b63b1dc commit 33a0003

File tree

3 files changed

+111
-23
lines changed

3 files changed

+111
-23
lines changed
Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
2-
<Import Project="..\..\DelegateDecompiler.props" />
3-
4-
<PropertyGroup>
5-
<TargetFramework>net45</TargetFramework>
6-
<Copyright>Copyright © Dave Glick 2014, Jon Smith 2014, Alexander Zaytsev 2014 - 2017</Copyright>
7-
</PropertyGroup>
8-
9-
<ItemGroup>
10-
<PackageReference Include="nunit" Version="3.7.1" />
11-
</ItemGroup>
12-
13-
<ItemGroup Condition="'$(TargetFramework)' != 'net40'">
14-
<PackageReference Include="NUnit3TestAdapter" Version="3.8.0" />
15-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
16-
</ItemGroup>
17-
18-
<ItemGroup>
19-
<ProjectReference Include="..\DelegateDecompiler.EntityFramework\DelegateDecompiler.EntityFramework.csproj" />
20-
<ProjectReference Include="..\DelegateDecompiler.Tests\DelegateDecompiler.Tests.csproj" />
21-
</ItemGroup>
22-
23-
</Project>
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<Import Project="..\..\DelegateDecompiler.props" />
3+
4+
<PropertyGroup>
5+
<TargetFramework>net45</TargetFramework>
6+
<Copyright>Copyright © Dave Glick 2014, Jon Smith 2014, Alexander Zaytsev 2014 - 2017</Copyright>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="nunit" Version="3.7.1" />
11+
</ItemGroup>
12+
13+
<ItemGroup Condition="'$(TargetFramework)' != 'net40'">
14+
<PackageReference Include="NUnit3TestAdapter" Version="3.8.0" />
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\DelegateDecompiler.EntityFramework\DelegateDecompiler.EntityFramework.csproj" />
20+
<ProjectReference Include="..\DelegateDecompiler.Tests\DelegateDecompiler.Tests.csproj" />
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Contributed by @JonPSmith (GitHub) www.thereformedprogrammer.com
2+
3+
using System.Linq;
4+
using DelegateDecompiler.EntityFramework.Tests.Helpers;
5+
using NUnit.Framework;
6+
using DelegateDecompiler.EntityFramework.Tests.EfItems;
7+
using System.Data.Entity;
8+
using System.Collections.Generic;
9+
10+
namespace DelegateDecompiler.EntityFramework.Tests.TestGroup05BasicFeatures
11+
{
12+
class Test01Include
13+
{
14+
private ClassEnvironment classEnv;
15+
16+
[OneTimeSetUp]
17+
public void SetUpFixture()
18+
{
19+
classEnv = new ClassEnvironment();
20+
}
21+
22+
[Computed]
23+
private static bool ComputedSample() { return true; }
24+
25+
[Test]
26+
public void TestInclude()
27+
{
28+
using (var db = new EfTestDbContext())
29+
using (var env = new MethodEnvironment(classEnv))
30+
{
31+
//SETUP
32+
var linq = db.EfParents.Where(p => true).Include(p => p.Children).ToList();
33+
34+
//ATTEMPT
35+
env.AboutToUseDelegateDecompiler();
36+
var dd = env.Db.EfParents.Where(p => ComputedSample()).Include(p => p.Children).Decompile().ToList();
37+
38+
//VERIFY
39+
env.CompareAndLogList(linq, dd);
40+
}
41+
}
42+
43+
}
44+
}

src/DelegateDecompiler/DecompileExpressionVisitor.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,50 @@ public static Expression Decompile(Expression expression)
1414
return new DecompileExpressionVisitor().Visit(expression);
1515
}
1616

17+
private static readonly object NULL = new object(); // for use as a dictionary key
18+
private readonly Dictionary<object, Expression> visitedConstants;
19+
20+
private bool hasAnyChanges = false;
21+
public override Expression Visit(Expression node)
22+
{
23+
var result = base.Visit(node);
24+
if (result != node)
25+
hasAnyChanges = true;
26+
return result;
27+
}
28+
29+
private DecompileExpressionVisitor(Dictionary<object, Expression> sharedVisitedConstants = null)
30+
{
31+
this.visitedConstants = sharedVisitedConstants ?? new Dictionary<object, Expression>();
32+
}
33+
34+
protected override Expression VisitConstant(ConstantExpression node)
35+
{
36+
Expression result;
37+
if (visitedConstants.TryGetValue(node.Value ?? NULL, out result))
38+
{
39+
return result; // avoid infinite recursion
40+
}
41+
42+
if (typeof(IQueryable).IsAssignableFrom(node.Type))
43+
{
44+
visitedConstants.Add(node.Value ?? NULL, node);
45+
46+
var value = (IQueryable)node.Value;
47+
var childVisitor = new DecompileExpressionVisitor(visitedConstants);
48+
result = childVisitor.Visit(value.Expression);
49+
50+
if (childVisitor.hasAnyChanges)
51+
{
52+
result = Expression.Constant(value.Provider.CreateQuery(result), node.Type);
53+
visitedConstants[node.Value ?? NULL] = result;
54+
return result;
55+
}
56+
}
57+
58+
return node;
59+
}
60+
1761
protected override Expression VisitMember(MemberExpression node)
1862
{
1963
if (ShouldDecompile(node.Member))

0 commit comments

Comments
 (0)