Linq表达式组合 [英] Linq Expression Calling Combines
本文介绍了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:
-
f3
只有两个参数。 -
f1
,f2
和f3
都具有完全相同的方法签名
f3
has exactly two parameters.f1
,f2
andf3
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屋!
查看全文