假设我有一个Expression<Func<Arg1,Arg2,ReturnType>>
,如何将其转换为Expression<Func<Arg1,ReturnType>>
?
我已经定义了一个Expression<Func<Individual, Record, bool>>
,如果允许个人查看记录,则该返回true。我想在个人或记录的DbContext上的Where子句中使用此表达式。示例:
Expression<Func<Individual,Record,bool>> expression = GetFilterExpression();
// Get All the records that an individual can review...
Individual ind = SomeIndividual();
Expression<Func<Individual,bool>> canBeViewedBy = Utility.ReplaceParameter(expression, 0, ind);
List<Record> records = _context.Records.Where(canBeViewedBy).ToList();
// Get All the individuals that can review the record...
Record record = SomeRecord();
Expression<Func<Record,bool>> canView = Utility.ReplaceParameter(expression, 1, record);
List<Individual> individuals = _context.Individuals.Where(canView).ToList();
在我的实际应用程序中,我有一个CanIndividualViewRecordSpecification
,当前会生成一个Expression<Func<Record,bool>>
。我希望它也能够生成Expression<Func<Individual,bool>>
,而不必多次定义过滤器。
答案 0 :(得分:1)
我最终自己解决了。
public static class ExpressionHelpers
{
public static Expression<Func<TArg2, TReturn>> ReplaceParamter<TArg1, TArg2, TReturn>(this Expression<Func<TArg1, TArg2, TReturn>> source, TArg1 arg1)
{
var t1Param = Expression.Constant(arg1);
var t2Param = Expression.Parameter(typeof(TArg2));
var body = source.Body
.ReplaceParameter(source.Parameters[0], t1Param)
.ReplaceParameter(source.Parameters[1], t2Param);
return Expression.Lambda<Func<TArg2, TReturn>>(body, t2Param);
}
public static Expression<Func<TArg1, TReturn>> ReplaceParamter<TArg1, TArg2, TReturn>(this Expression<Func<TArg1, TArg2, TReturn>> source, TArg2 arg2)
{
var t1Param = Expression.Parameter(typeof(TArg1));
var t2Param = Expression.Constant(arg2);
var body = source.Body
.ReplaceParameter(source.Parameters[0], t1Param)
.ReplaceParameter(source.Parameters[1], t2Param);
return Expression.Lambda<Func<TArg1, TReturn>>(body, t1Param);
}
public static Expression ReplaceParameter(this Expression expression,
ParameterExpression toReplace,
Expression newExpression)
{
return new ParameterReplaceVisitor(toReplace, newExpression)
.Visit(expression);
}
}
public class ParameterReplaceVisitor : ExpressionVisitor
{
private ParameterExpression from;
private Expression to;
public ParameterReplaceVisitor(ParameterExpression from, Expression to)
{
this.from = from;
this.to = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return node == from ? to : base.VisitParameter(node);
}
}
示例:
Expression<Func<Individual,Record,bool>> expression = GetFilterExpression();
// Get All the records that an individual can review...
Individual ind = SomeIndividual();
Expression<Func<Record,bool>> canBeViewedBy = expression.ReplaceParameter(ind);
List<Record> records = _context.Records.Where(canBeViewedBy).ToList();
// Get All the individuals that can review the record...
Record record = SomeRecord();
Expression<Func<Individual,bool>> canView = expression.ReplaceParameter(record);
List<Individual> individuals = _context.Individuals.Where(canView).ToList();