Linq表达式组合 [英] Linq Expression Calling Combines

查看:183
本文介绍了Linq表达式组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何组合这些表达式

Expression<Func<int, int>> f1 = i => i + 1;
Expression<Func<int, int>> f2 = i => i + 2;
Expression<Func<int, int, int>> f3 = (i, j) => i * j;

Expression<Func<int, int>> f4 = i =>(i+1)*(i+2);

在运行时?
谢谢

while running? thanks

这里是代码。
我想编写一个扩展方法,但它不能在linq2entities中工作

here's the code. I want to write a extend method but it don't work in linq2entities

public static IQueryable<TRe> LeftJoin<TLeft, TRight, TKey, TRe>(this IQueryable<TLeft> left, IQueryable<TRight> right, Expression<Func<TLeft, TKey>> leftKeySel, Expression<Func<TRight, TKey>> rightKeySel, Expression<Func<TLeft, TRight, TRe>> reSel)
{
    return left.GroupJoin(right, leftKeySel, rightKeySel, (l, r) => new { l, r }).SelectMany(p => p.r.DefaultIfEmpty(), (p, r) => new { p.l, r }).Select1(p => p.l, p => p.r, reSel);
}
public static IQueryable<TRe> Select1<TSrc, T1, T2, TRe>(this IQueryable<TSrc> src, Expression<Func<TSrc, T1>> f1, Expression<Func<TSrc, T2>> f2, Expression<Func<T1, T2, TRe>> func)
{

    var p = Expression.Parameter(typeof(TSrc));

    var a = Expression.Invoke(f1, p);
    var b = Expression.Invoke(f2, p);
    var c = Expression.Invoke(func, a, b);

    return src.Select(Expression.Lambda<Func<TSrc, TRe>>(c, p));
}

,此代码叫LeftJoin方法:

and this code called LeftJoin method:

        var re = _db.Accounts.OrderBy(p => p.LoginDays).Take(100).LeftJoin(_db.PasswordHistorys, p => p.Email, p => p.Email, (a, b) => new
        {
            a,
            b.PasswordOld
        });


推荐答案

你可以这样做:

var p = Expression.Parameter(typeof(int), "i");
var r = Expression
    .Invoke(f3, new[] { 
        Expression.Invoke(f1, p), 
        Expression.Invoke(f2, p) });

Expression<Func<int, int>> lam = Expression.Lambda<Func<int, int>>(r, p);

根据评论,可以这样做:

As per comments, it is possible to do this:

var p = Expression.Parameter(typeof(int), "i");
var lam = Expression.Lambda<Func<int, int>>(Expression.Multiply(f1.Body, f2.Body), p);

var p = Expression.Parameter(typeof(int), "i");
var lam = Expression.Lambda<Func<int, int>>(Expression.Add(f1.Body, f2.Body), p);






表情访问者的解决方案



所以,我想出了一点点,用 f1 替换参数引用f2

但是,它做出以下假设:


Solution with expression visitors

So, I managed to come up with a bit of a hack to replace the parameter references with f1 and f2.
However, it makes the following assumptions:


  1. f3 只有两个参数。

  2. f1 f2 f3 都具有完全相同的方法签名

  1. f3 has exactly two parameters.
  2. f1 ,f2 and f3 all have the exact same method signatures

这是实现:

public class SuperHack : ExpressionVisitor
{   
    private Dictionary<ParameterExpression, LambdaExpression> _replacements;
    private ParameterExpression _newParameter;
    public SuperHack(Dictionary<ParameterExpression, LambdaExpression> replacements, ParameterExpression newParameter)
    {
        _replacements = replacements ?? new Dictionary<ParameterExpression, LambdaExpression>();
        _newParameter = newParameter;
    }

    public Expression Modify(Expression expression)
    {
        var res = Visit(expression);
        return res;
    }

    protected override Expression VisitLambda<T>(Expression<T> e)
    {
        return Expression.Lambda(Visit(e.Body), _newParameter);
    }

    protected override Expression VisitParameter(ParameterExpression e)
    {
        if (_replacements.ContainsKey(e))
            return Visit(Expression.Lambda(_replacements[e].Body, _newParameter).Body);

        return base.VisitParameter(_newParameter);
    }
}

这是你如何使用它:

Expression<Func<int, int>> f1 = i => i + 1;
Expression<Func<int, int>> f2 = i => i + 2;
Expression<Func<int, int, int>> f3 = (i, j) => i * j;

var @params = f3.Parameters;
var mapping = new Dictionary<ParameterExpression, LambdaExpression>
{
    {@params[0], f1},
    {@params[1], f2}
};

var p = Expression.Parameter(typeof(int), "i");
var f4 = new SuperHack(mapping, p).Modify(f3) as Expression<Func<int,int>>;

结果是:

i => ((i + 1) * (i + 2))

不需要调用

这篇关于Linq表达式组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆