[英]Adding to Lambda Expression and work with Entity Framework
If I want retrieve more columns with an already existing lambda tree expression like below, how would I do that? 如果我想要检索更多列已经存在的lambda树表达式,如下所示,我该怎么做? This works with Entity Frameworks and want it to still work.
这适用于实体框架,并希望它仍然有效。
Expression<Func<DivisionTeam, DirectorTeamModel>> columns= (d) => new DirectorTeamModel
{
Id = d.Id,
TeamId = d.Team.Id
};
if (criteria.Template == ExportTemplate.Import || criteria.Template == ExportTemplate.Default)
{
// Retrieve additional columns from "columns" expression tree
}
return _divisionTeamsRepository.GetPagedResults(criteria.Page, criteria.PageSize, @where.Expand(), string.Format("{0} {1}", criteria.SortOrder, criteria.SortDirection), columns);
Given two "selector" expressions, you've to take the bindings from their MemberInitExpression
and create a new expression using all the bindings. 给定两个“selector”表达式,您将从其
MemberInitExpression
获取绑定并使用所有绑定创建一个新表达式。 But this expression isn't going to work, since it uses two different parameter expressions for one single parameter. 但是这个表达式不起作用,因为它为一个参数使用两个不同的参数表达式。 We need to fix that too.
我们也需要解决这个问题。
Given... 鉴于...
Expression<Func<TSource, TResult>> left = ... // columns
Expression<Func<TSource, TResult>> right = ... // more columns
...take the bindings... ......拿绑定......
var leftInit = left.Body as MemberInitExpression;
var rightInit = right.Body as MemberInitExpression;
var bindings = leftInit.Bindings.Concat(rightInit.Bindings);
...create a new expression... ......创造一个新的表达......
var result = Expression.Lambda<Func<TSource, TResult>>(
Expression.MemberInit(Expression.New(typeof(TResult)), bindings), ???);
...BUT, need single parameter... ...但是,需要单个参数......
var binder = new ParameterBinder(left.Parameters[0], right.Parameters[0]);
var bindings = binder.Visit(leftInit.Bindings.Concat(rightInit.Bindings));
// now, just use right.Parameters[0] as parameter...
And, replacing parameters works well using an expression visitor: 并且,使用表达式访问者更换参数效果很好:
class ParameterBinder : ExpressionVisitor
{
readonly ParameterExpression parameter;
readonly Expression replacement;
public ParameterBinder(ParameterExpression parameter, Expression replacement)
{
this.parameter = parameter;
this.replacement = replacement;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == parameter)
return replacement;
return base.VisitParameter(node);
}
}
Abstracting this plumbing stuff works quite well. 抽象这个管道的东西工作得很好。 In fact, you can just use an existing library (spoiler: I'm the author), which should lead to something like that:
事实上,你可以使用现有的库 (剧透:我是作者),这应该会导致类似的东西:
var merged = columns.Apply(moreColumns);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.