Skip to content

Commit 85cacd9

Browse files
DocSvartzDocSvartz
authored andcommitted
start
1 parent 155a723 commit 85cacd9

File tree

3 files changed

+136
-6
lines changed

3 files changed

+136
-6
lines changed

src/Mapster.EFCore.Tests/EFCoreTest.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ public void TestFindObject()
3333
}
3434
}
3535
};
36-
var poco = context.Students.Include(it => it.Enrollments)
36+
var poco = context.Students
37+
.Include(it => it.Enrollments)
3738
.First(it => it.ID == dto.ID);
3839

3940
dto.BuildAdapter()
@@ -56,15 +57,21 @@ public void MapperInstance_From_OrderBy()
5657

5758
var mapsterInstance = new Mapper();
5859

59-
var query = context.Students.Include(it => it.Enrollments);
60-
var orderedQuery = mapsterInstance.From(query)
61-
.ProjectToType<StudentDto>()
60+
TypeAdapterConfig<Student, StudentDto>
61+
.NewConfig()
62+
.Map(x => x.Enrollments, x => x.Enrollments);
63+
64+
65+
var query = context.Students
66+
.Include(it => it.Enrollments.OrderByDescending(x=>x.StudentID).Take(1))
67+
.Include(it=> it.Students)
68+
.EFCoreProjectToType<StudentDto>()
6269
.OrderBy(s => s.LastName);
6370

64-
var first = orderedQuery.First();
71+
var first = query.First();
6572
first.LastName.ShouldBe("Alexander");
6673

67-
var last = orderedQuery.Last();
74+
var last = query.Last();
6875
last.LastName.ShouldBe("Olivetto");
6976
}
7077
}

src/Mapster.EFCore.Tests/Models/Student.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ public class Student
1111
public DateTime EnrollmentDate { get; set; }
1212

1313
public ICollection<Enrollment> Enrollments { get; set; }
14+
15+
public ICollection<Student> Students { get; set; }
1416
}
1517
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
using System.Collections.Generic;
2+
using System.Diagnostics.CodeAnalysis;
3+
using System.Linq;
4+
using System.Linq.Expressions;
5+
using System.Security.Cryptography.X509Certificates;
6+
7+
namespace Mapster.EFCore
8+
{
9+
public static class EFCoreExtensions
10+
{
11+
public static IQueryable<TDestination> EFCoreProjectToType<TDestination>(this IQueryable source, TypeAdapterConfig? config = null)
12+
{
13+
14+
var allInclude = new IncludeVisiter();
15+
16+
allInclude.Visit(source.Expression);
17+
18+
if (config == null)
19+
{
20+
config = TypeAdapterConfig.GlobalSettings
21+
.Clone()
22+
.ForType(source.ElementType, typeof(TDestination))
23+
.Config;
24+
}
25+
else
26+
{
27+
config = config.Clone()
28+
.ForType(source.ElementType, typeof(TDestination))
29+
.Config;
30+
}
31+
32+
33+
return source.ProjectToType<TDestination>(config);
34+
35+
// var mockCall = config.GetProjectionCallExpression(source.ElementType, typeof(TDestination));
36+
// var sourceCall = Expression.Call(mockCall.Method, source.Expression, mockCall.Arguments[1]);
37+
// return source.Provider.CreateQuery<TDestination>(sourceCall);
38+
}
39+
40+
}
41+
42+
internal class IncludeVisiter : ExpressionVisitor
43+
{
44+
[return: NotNullIfNotNull("node")]
45+
public override Expression Visit(Expression node)
46+
{
47+
if (node == null)
48+
return null;
49+
switch (node.NodeType)
50+
{
51+
case ExpressionType.Call:
52+
{
53+
if(IsInclude(node))
54+
{
55+
var QuoteVisiter = new QuoteVisiter();
56+
QuoteVisiter.Visit(node);
57+
58+
var memberv = new MemeberVisiter();
59+
memberv.Visit(QuoteVisiter.Quotes[0]);
60+
}
61+
return base.Visit(node);
62+
}
63+
}
64+
65+
return base.Visit(node);
66+
}
67+
68+
public List<Expression> IncludeExpression { get; protected set; } = new();
69+
private bool IsInclude (Expression node) => node.Type.Name.StartsWith("IIncludableQueryable");
70+
71+
}
72+
73+
internal class QuoteVisiter: ExpressionVisitor
74+
{
75+
public List<UnaryExpression> Quotes { get; private set; } = new();
76+
77+
public override Expression Visit(Expression node)
78+
{
79+
if (node == null)
80+
return null;
81+
switch (node.NodeType)
82+
{
83+
case ExpressionType.Quote:
84+
{
85+
Quotes.Add((UnaryExpression)node);
86+
return base.Visit(node);
87+
}
88+
}
89+
90+
return base.Visit(node);
91+
92+
}
93+
}
94+
95+
internal class MemeberVisiter : ExpressionVisitor
96+
{
97+
public string? Key { get; private set; }
98+
99+
public override Expression Visit(Expression node)
100+
{
101+
102+
103+
if (node == null)
104+
return null;
105+
switch (node.NodeType)
106+
{
107+
case ExpressionType.MemberAccess:
108+
{
109+
if (string.IsNullOrEmpty(Key))
110+
Key = ((MemberExpression)node).Member.Name;
111+
112+
return base.Visit(node);
113+
}
114+
}
115+
116+
return base.Visit(node);
117+
118+
119+
}
120+
}
121+
}

0 commit comments

Comments
 (0)