以前用EF的时候,由于where的时候有Expression<Func
翻译过来吧,就是说Func
1
Expression<Func<int>> myExpression = () => 10;
其实吧, 多用一下你就知道了.Func
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.And));
}
private static Expression<Func<T, bool>> Compose<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second, Func<Expression, Expression, Expression> merge)
{
Expression expression = new ParameterRebinder(second.Parameters[0], first.Parameters[0]).Visit(second.Body);
return Expression.Lambda<Func<T, bool>>(merge(first.Body, expression), first.Parameters);
}
public static Expression<Func<T, bool>> False<T>()
{
return item => false;
}
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> predicate)
{
return Expression.Lambda<Func<T, bool>>(Expression.Not(predicate.Body), predicate.Parameters);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.Or));
}
public static Expression<Func<T, bool>> True<T>()
{
return item => true;
}
private sealed class ParameterRebinder : ExpressionVisitor
{
private readonly ParameterExpression m_From;
private readonly ParameterExpression m_To;
public ParameterRebinder(ParameterExpression from, ParameterExpression to)
{
this.m_From = from;
this.m_To = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == this.m_From)
{
node = this.m_To;
}
return base.VisitParameter(node);
}
}
}
表达式树恶心的地方,我写一个orderby给你看看.
1
2
3
4
5
6
7
8
9
10
11
12
public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
{
string command = desc ? "OrderByDescending" : "OrderBy";
var type = typeof(TEntity);//实体的类型
var property = type.GetProperty(orderByProperty);
var parameter = Expression.Parameter(type, "o");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExpression));
return source.Provider.CreateQuery<TEntity>(resultExpression);
}
动态linq是需要反射的.而且这种写法不利于调试.因为你特么完全不知道生成的什么鬼,除非你对这玩意真的很熟.好吧,你赢了.
参考链接:
- [Why would you use Expression<Func
> rather than Func ?](https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct) - Entity Framework - Func引起的数据库全表查询
- 通过已有Func构造Expression表达式问题
When I was using EF (Entity Framework), there were two types of query conditions for where: Expression<Func
To translate: Func
1
Expression<Func<int>> myExpression = () => 10;
Actually, you’ll understand once you use it more. Func
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.And));
}
private static Expression<Func<T, bool>> Compose<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second, Func<Expression, Expression, Expression> merge)
{
Expression expression = new ParameterRebinder(second.Parameters[0], first.Parameters[0]).Visit(second.Body);
return Expression.Lambda<Func<T, bool>>(merge(first.Body, expression), first.Parameters);
}
public static Expression<Func<T, bool>> False<T>()
{
return item => false;
}
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> predicate)
{
return Expression.Lambda<Func<T, bool>>(Expression.Not(predicate.Body), predicate.Parameters);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.Or));
}
public static Expression<Func<T, bool>> True<T>()
{
return item => true;
}
private sealed class ParameterRebinder : ExpressionVisitor
{
private readonly ParameterExpression m_From;
private readonly ParameterExpression m_To;
public ParameterRebinder(ParameterExpression from, ParameterExpression to)
{
this.m_From = from;
this.m_To = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == this.m_From)
{
node = this.m_To;
}
return base.VisitParameter(node);
}
}
}
The annoying part about expression trees, let me show you an orderby example:
1
2
3
4
5
6
7
8
9
10
11
12
public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
{
string command = desc ? "OrderByDescending" : "OrderBy";
var type = typeof(TEntity);//Entity type
var property = type.GetProperty(orderByProperty);
var parameter = Expression.Parameter(type, "o");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExpression));
return source.Provider.CreateQuery<TEntity>(resultExpression);
}
Dynamic LINQ requires reflection. And this writing style is not conducive to debugging. Because you have no idea what the hell is being generated, unless you’re really familiar with this stuff. Well, you win.
Reference Links:
- [Why would you use Expression<Func
> rather than Func ?](https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct) - Entity Framework - Func引起的数据库全表查询
- 通过已有Func构造Expression表达式问题
以前EFを使っていた時、whereにはExpression<Func
翻訳すると、Func
1
Expression<Func<int>> myExpression = () => 10;
実際、もっと使えば分かります。Func
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.And));
}
private static Expression<Func<T, bool>> Compose<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second, Func<Expression, Expression, Expression> merge)
{
Expression expression = new ParameterRebinder(second.Parameters[0], first.Parameters[0]).Visit(second.Body);
return Expression.Lambda<Func<T, bool>>(merge(first.Body, expression), first.Parameters);
}
public static Expression<Func<T, bool>> False<T>()
{
return item => false;
}
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> predicate)
{
return Expression.Lambda<Func<T, bool>>(Expression.Not(predicate.Body), predicate.Parameters);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.Or));
}
public static Expression<Func<T, bool>> True<T>()
{
return item => true;
}
private sealed class ParameterRebinder : ExpressionVisitor
{
private readonly ParameterExpression m_From;
private readonly ParameterExpression m_To;
public ParameterRebinder(ParameterExpression from, ParameterExpression to)
{
this.m_From = from;
this.m_To = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == this.m_From)
{
node = this.m_To;
}
return base.VisitParameter(node);
}
}
}
式ツリーの厄介な部分、orderbyの例を見せます:
1
2
3
4
5
6
7
8
9
10
11
12
public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
{
string command = desc ? "OrderByDescending" : "OrderBy";
var type = typeof(TEntity);//エンティティの型
var property = type.GetProperty(orderByProperty);
var parameter = Expression.Parameter(type, "o");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExpression));
return source.Provider.CreateQuery<TEntity>(resultExpression);
}
動的LINQにはリフレクションが必要です。そして、この書き方はデバッグに適していません。生成されるものが何なのか全く分からないからです。このことに本当に精通していない限り。まあ、あなたの勝ちです。
参考リンク:
- [Why would you use Expression<Func
> rather than Func ?](https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct) - Entity Framework - Func引起的数据库全表查询
- 通过已有Func构造Expression表达式问题
Когда я использовал EF (Entity Framework), для where было два типа условий запроса: Expression<Func
Переводя: Func
1
Expression<Func<int>> myExpression = () => 10;
На самом деле, вы поймете, как только будете использовать это больше. Func
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.And));
}
private static Expression<Func<T, bool>> Compose<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second, Func<Expression, Expression, Expression> merge)
{
Expression expression = new ParameterRebinder(second.Parameters[0], first.Parameters[0]).Visit(second.Body);
return Expression.Lambda<Func<T, bool>>(merge(first.Body, expression), first.Parameters);
}
public static Expression<Func<T, bool>> False<T>()
{
return item => false;
}
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> predicate)
{
return Expression.Lambda<Func<T, bool>>(Expression.Not(predicate.Body), predicate.Parameters);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.Or));
}
public static Expression<Func<T, bool>> True<T>()
{
return item => true;
}
private sealed class ParameterRebinder : ExpressionVisitor
{
private readonly ParameterExpression m_From;
private readonly ParameterExpression m_To;
public ParameterRebinder(ParameterExpression from, ParameterExpression to)
{
this.m_From = from;
this.m_To = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == this.m_From)
{
node = this.m_To;
}
return base.VisitParameter(node);
}
}
}
Раздражающая часть деревьев выражений, позвольте показать вам пример orderby:
1
2
3
4
5
6
7
8
9
10
11
12
public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
{
string command = desc ? "OrderByDescending" : "OrderBy";
var type = typeof(TEntity);//Тип сущности
var property = type.GetProperty(orderByProperty);
var parameter = Expression.Parameter(type, "o");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExpression));
return source.Provider.CreateQuery<TEntity>(resultExpression);
}
Динамический LINQ требует рефлексии. И этот стиль написания не способствует отладке. Потому что вы понятия не имеете, что черт возьми генерируется, если только вы не очень хорошо знакомы с этим. Ну, вы выиграли.
Ссылки:
- [Why would you use Expression<Func
> rather than Func ?](https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct) - Entity Framework - Func引起的数据库全表查询
- 通过已有Func构造Expression表达式问题